投稿日: | 最終更新日:
Django Modelsを使ってデータを登録する
Anaconda・Django1.11.3環境に、Modelsを使って、フォームに入力したデータを登録します。
Modelとは?
Modelは、サイトを構成するデータソース(主にデータベース)へのアクセスを請け負います。理解するにはデータベースの知識も必要になるため、Djangoでの難所です。
CRUD
難所ですが、以下のシンプルなCRUDのルールを覚えれば実現可能です。CRUDができれば、一般的なWebアプリケーションは開発できます。
- Create(生成)
- Read(読み取り)
- Update(更新)
- Delete(削除)
基礎知識とModelクラス(理論)
データベースにテーブルを作るDDL(Data Definition Language)は、以下のようになります。
CREATE TABLE "テーブル名" ( カラム1 データ型 {その他の制約}, カラム2 データ型 {その他の制約}, );
以下の表が、DDLとModelクラスがどのように紐づくかの関係図です。Modelクラスの場合も、データベースのDDLと同じ情報を持ちます。
DDL | Modelクラス |
---|---|
テーブル名 | クラス名 |
カラム名 | クラス変数名 |
データ型 | クラス変数に代入するオブジェクト(Fieldクラスのインスタンス) |
その他 | Fieldクラスのオプション |
この情報を元にした、Modelクラスの雛形は以下の通りです。
class テーブル名(Model): カラム名1 = データ型(その他の制約) カラム名2 = データ型(その他の制約)
実例
※ここで出てくるコードはあくまで実例なので、実際に書く必要はありません。
テーブル定義
論理名 | 物理名 |
---|---|
顧客テーブル | customer |
列
論理名 | 物理名 | データ型 | 長さ | 必須 | キー | 外部キー | 備考 |
---|---|---|---|---|---|---|---|
ID | id | INT | YES | PK | AUTO INCREMENT | ||
姓 | last_name | varchar | 20 | YES | |||
名 | last_name | varchar | 20 | YES | |||
Eメールアドレス | email_address | varchar | 255 | YES | UK | ||
メモ | memo | text |
DDL
CREATE TABLE customer ( id serial NOT NULL PRIMARY KEY, last_name varchar(20) NOT NULL, first_name varchar(20) NOT NULL, email_address varchar(255) NOT NULL UNIQUE, memo text );
Model
※ここで出てくるコードはあくまで実例なので、実際に書く必要はありません。
Fieldクラスのオプションに何も指定しなければ、NOT NULL制約がかかります。PRIMARY KEYとなるクラス変数を定義しない場合、idが自動的に定義されます。
from django.core.db import models class Customer(models.Model): # id = AutoField(primary_key=True) # 自動的に追加されるので定義不要 last_name = CharField(max_length=20) first_name = CharField(max_length=20) email_address = EmailField(max_length=255, unique=True) memo = TextField(null=True)
※Modelでは、幾つかの制約が暗黙的に定義されています。
migrateを実行
migrateとは、Modelクラスを定義したり、定義後のModelクラスに変更を加えたときに、 それらをデータベースのスキーマに反映するコマンドです。Djangoでは、migrateの履歴管理や一部のモジュールでデータベースを使います。
通常は、settings.pyにDBの設定を行った直後にmigrateを実施します。
- プロジェクトを作る( djang-admin.py startproject XXXXXX )
- settings.py にDBの設定を書く(DBAにsqlite3を使う場合は、この手順を省略する)
- migrateを実行する ( python manage.py migrate )
python projectname/manage.py migrate
環境
OS | CentOS 7.1.1503 |
---|---|
pyenv | 1.1.3-5-g7dae197 |
Anaconda | 3-4.3.0 |
MariaDB | 5.5.52-1.el7 |
Apache | 2.4.6 |
mod_wsgi | 4.5.14 |
Django | 1.11.3 |
Modelクラスを定義する
実際にModelクラスをmodels.pyに追加します。機能としましては、画面から投稿されたデータ検証し、検証結果に問題が無いデータをデータベースに保存するためのModelとします。
①models.pyに「Hello」モデルを記述します。
from django.db import models class Hello(models.Model): your_name = models.CharField(max_length=10) def __str__(self): return "<{0}>".format(self.your_name)
②Modelクラスをデータベースのスキーマに反映します。
Modelクラスをデータベースのスキーマに反映するには、2つの手順をふみます。
- データベースのスキーマとModelクラスの差を取り、変更処理が書かれているPythonファイルを生成する
- 変更処理が書かれているPythonファイルを使いデータベースのスキーマを変更する
※それぞれ manage.py で実行できます。
python manage.py makemigrations python manage.py migrate
Django ShellでModelを使う
実際にModelをDjango shellからModelを操作してCRUDの基礎を学びます。Django shellからModelを操作します。
①Django shellを起動します。プロジェクト名を「pj1」とします。アプリケーション名を「app1」とします。
python pj1/manage.py shell
②データを登録します。
>>> from app1.models import Hello >>> kenji = Hello.objects.create(your_name='Kenji') >>> print("id:{0}, your_name:{1}".format(kenji.id, kenji.your_name)) id:1, your_name:Kenji
>>> takuya = Hello.objects.create(your_name='Takuya') >>> print("id:{0}, your_name:{1}".format(takuya.id, takuya.your_name)) id:2, your_name:Takuya
③データを全件取得します。Hello.objects.all() で、無条件ですべてのデータを取得できます。
>>> Hello.objects.all() [<Hello: <Kenji>>, <Hello: <Takuya>>] >>> for h in Hello.objects.all(): print(h.your_name) ... Kenji Takuya
④idを指定して検索する場合など、必ず1件しかデータが取得できない場合、Hello.objects.get({パラメーター}) で検索します。
>>> h = Hello.objects.get(pk=1) >>> print(h.your_name) Kenji
⑤条件に一致するデータを検索する場合、Hello.objects.filter({パラメーター}) で検索します。
>>> h_qs = Hello.objects.filter(id__in=[1,2]) >>> for h in h_qs: print(h.your_name) ... Kenji Takuya >>> for h in h_qs.filter(your_name='Kenji'): print(h.your_name) ... Kenji
⑥データを更新します。インスタンス変数を上書きした後、XXX.save() メソッドを呼び出します。
>>> h = Hello.objects.get(pk=1) >>> print(h.your_name) Kenji
>>> h.your_name = 'Makoto' >>> h.save() >>> h = Hello.objects.get(pk=1) >>> print(h.your_name) Makoto
⑦データを削除します。データを更新する場合は、インスタンス変数を上書きした後、XXX.delete() メソッドを呼び出します。
>>> h = Hello.objects.get(pk=1) >>> h.delete() >>> h = Hello.objects.get(pk=1) Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/eiry/PycharmProjects/practice/venv/lib/python3.4/site-packages/django/db/models/manager.py", line 127, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Users/eiry/PycharmProjects/practice/venv/lib/python3.4/site-packages/django/db/models/query.py", line 334, in get self.model._meta.object_name hello.models.DoesNotExist: Hello matching query does not exist.
画面から入力されたデータをデータベースに保存
画面から入力されたデータを、Modelを使ってデータベースに保存します。
①forms.pyにHelloFormフォームを追加します。
vi pj1/app1/forms.py
以下のように編集します。
from django import forms class HelloForm(forms.Form): your_name = forms.CharField( label = '名前', max_length = 20, required=True, widget=forms.TextInput() ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['your_name'].widget.attrs['class'] = 'form-control'
②views.pyにビュー関数を追加します。
vi pj1/app1/views.py
以下のように編集します。
from django.shortcuts import redirect from . import forms, models def hello_models(request): form = HelloForm(request.POST or None) if form.is_valid(): models.Hello.objects.create(**form.cleaned_data) return redirect('app1:index') d = { 'form' : form, 'hello_qs': models.Hello.objects.all().order_by('-id'), } return render(request, 'models.html', d)
redirect(‘app1:index’)
redirect関数の引数には、「namespace:name」と書くことでURLConfから必要なURLを逆引きします。また、「URL:http://XXXXXX」を直接書くこともできます。
ビュー関数の中で「redirect(….)」と言う関数を呼び出していますが、これがPRGパターンのR(Redirect)に該当するところです。
③templatesディレクトリにmodels.htmlを追加します。
vi pj1/app1/templates/models.html
以下のように編集します。base.htmlは以前の記事を参照して下さい。
{% extends "base.html" %} {% block content %} <div class="container"> {{ message }} <h1>your_nameを登録する</h1> <h2>登録</h2> <form method="post" action=""> <div class="form-group"> {{ form.errors.your_name }} <label>{{ form.your_name.label }} {{ form.your_name }}</label><br> <input type="submit" class="btn btn-primary" value="送信"> {% csrf_token %} </div> </form> <hr> <h2>一覧</h2> {% for h in hello_qs %} {{ h.your_name }}<br> {% endfor %} </div> {% endblock %}
Djangoは、この攻撃に対抗する手段としてPOST時に暗号論的擬似乱数値をHIDDENに埋め込む方法が採用されています。 テンプレートの中で「{% csrf_token %}」と言う記述がHIDDENに暗号論的擬似乱数値を埋め込んでいる所です。 これを記述しないと、POST時にセキュリティーエラーが発生します。
④最後にURLConfを書きます。
vi pj1/app1/urls.py
以下のように編集します。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.index, name='index'), ・・・(省略)・・・・ url(r'^models/$', views.hello_models, name="hello_models"), ]
⑤簡易Webサーバを立ち上げます。
python pj1/manage.py runserver 0.0.0.0:8000
⑥ホスト環境のブラウザから、以下のURLを入力します。
http://localhost:8000/models/
⑦動作確認します。入力フォームに名前を入力して送信ボタンを押すと、your_nameに情報が登録されます。
画面を表示したとき | エラーが発生せず、画面が表示できることを確認します。 |
---|---|
名前に何も入力しない場合 | 「このフィールドは必須です。」と言うメッセージが表示されることを確認します。 |
名前に「テスト名」と入力した場合 | 『一覧』の下に「テスト名」と表示されることを確認します。 |
- Python 114
- 制作 54
- RaspberryPi 41
- Django 40
- WordPress 40
- Linux 27
- VPS 22
- JavaScript 21
- PHP 20
- HTML・CSS 19
- AWS 16
- 仮想環境 15
- レスポンシブデザイン 13
- マイコン 11
- WEB全般 11
- 動画製作 9
- Webサービス 8
- 統合開発環境 8
- 機械学習 8
- PyCharm 7
- jQuery 7
- AfterEffects 7
- 起業・設立 7
- Django REST framework 6
- C# 6
- デザイン 6
- SEO 6
- pydata 6
- Visual Studio 5
- 数学 5
- 携帯サイト 5
- heroku 5
- Mac 5
- illustrator 5
- node.js 5
- Anaconda 5
- Nginx 4
- Jupyter Notebook 4
- インフラ 4
- Google Colaboratory 4
- symfony 4
- Webスクレイピング 3
- photoshop 3
- Go言語 3
- PC 3
- ツール 3
- Docker 3
- facebook 3
- 作業効率化 3
- データベース 3
- Cloud9 3
- コマンド 2
- micro:bit 2
- Kali Linux 2
- Webサーバー 2
- MariaDB 2
- ドローン 2
- コンテナ 2
- DaVinci Resolve 2
- ネットワーク 2
- Java 2
- movie 2
- PCDJ 2
- 音楽 2
- XSERVER 2
- Ansible 1
- Vue.js 1
- JSON 1
- Bootstrap 1
- バージョン管理システム 1
- SSL 1
- S3 1
- ムームードメイン 1
- ネットワーク 1
- アニメーション 1
- D3.js 1
- Rhino 1
- アニメ 1
- git 1
- windows 1
- アクセス解析 1
- スマートフォン 1
- アフィリエイトノウハウ 1
- 知識 1
- TypeScript 1
- 役立つ本・書籍 1
- データサイエンス 1
- ESP32 1
- AI 1
- ownCloud 1
- API 1