Djangoのチュートリアル 2 モデルを作成する
前回の記事で、Djangoのインストールと非常に簡単なViewの作り方まで説明しました。
pyhaya.hatenablog.com
今回は、これにモデルを加えてみたいと思います。具体的には、Question
とChoice
という2つのモデルを作って、pollsアプリケーションで扱うデータ用のデータベースを整備します。
この記事の内容の作業環境は
- Python3.6.5
- Django2.1.2
のようになっています
モデルとは
Djangoに限ったことではありませんが、アプリケーションではデータベースを必ずといっていいほど使います。ユーザーの入力やページの現在の状況などのデータを格納するためにデータベースは欠かせません。
データベースには様々な種類があります。例えば有名なものだとMySQLやPostgresなどがあります。
DjangoではModelというものを作成して、データベース構成を決定します。まず、データベースのテーブルを作ります。manage.py
があるディレクトリに移動して次のコマンドを実行します。
$ python manage.py migrate
これを実行すると
Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK
のような表示が出て、データベースにテーブルが作成されます。
モデルを作る
では、実際にモデルを作ってみます。前回作ったpollsディレクトリで作業を行います。
polls/models.py
from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)
ここでQuestion
クラスとChoice
クラスは、それぞれ質問とそれに対する回答を表すモデルです。それぞれmodels.Model
クラスを継承しているのが見て取れると思います。これがモデルのテンプレートです。では各モデルを1つ1つ見ていきます。
Question
クラス
このクラスは2つのフィールドquestion_text
とpub_date
を持っています。これらにはそれぞれCharField
やDateTimeField
が紐づけられています。この「~Field」という名前のものを使うことによって各フィールドにどのような種類のフィールドを設定するか決定しています。例えば、
Field名 | フィールドの種類 |
---|---|
CharField |
文字列 |
TextField> |
テキスト |
IntegerField |
数値 |
DateTimeField |
日付 |
などがあります。Fieldには本当に多くの種類があります。ほかのフィールドが知りたい方は以下のサイトが非常に見やすいと思います。
opendata-web.site
CharField
とTextField
はどう違うのかぱっと見分かりにくいですが、TextField
はブログ本文など、より長い文章を考えるときに使います。今回はquestion_text
は質問文なのでCharField
を使い、pub_date
は質問が投稿された日付を示しているのでDateTimeField
になっています。
ここで重要なのは、question_text
やpub_date
といった変数名はデータベースのフィールド名として使うということです。
Choice
クラス
Choice
クラスはQuestion
クラスと比べると複雑です。この複雑さの原因は一行目のForeignKey
です。これはこのクラスのQuestion
クラスとの関係を示しています。「各質問には選択肢があるよ」ということだと考えていれば大丈夫でしょう。
しかし1つだけ考えなくてはいけないことがあります。それはモデル同士が「一対一」、「多対一」、「一対多」、「多対多」のどれに対応するかという点です。今回の場合には、「一対多」に対応します。なぜなら質問1つに対して選択肢は複数あるからです。ForeignKey
というのは普通は「多」に対応するモデル(今回の場合には選択肢)に書くことが多いです。(多対多の場合にはManyToManyField
を使います)
ForeignKey
の役割はわかりました。ではその引数のon_delete
は何を表しているのでしょう。この値はForeignKey
で参照しているオブジェクトが削除されたときに対応するオブジェクトをどうするかを決めるパラメータです。このパラメータはDjango2系では必須になっています。選択肢には次のものがあります。
パラメータ | 説明 |
---|---|
models.CASCADE |
こちらも同様に削除する |
models.PROTECT |
こちらは削除しない |
models.SET_NULL |
nullオプションがTrueの時にフィールドをnullにする |
models.SET_DEFAULT |
デフォルト値が設定されているならその値にする |
on_delete
の振る舞いについては以下のサイトがわかりやすいです。
codelab.website
データベースにpollsで使うフィールドを作成する
モデルができたので、pollsアプリケーションで使うフィールドをデータベースに作成しましょう。その前に、このプロジェクトにpollsアプリケーションが存在することを教えてあげなければなりません。そのためには、一番上位のフォルダ、mysite
にpollsアプリケーションを登録します。
mysite/settings.py
#... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'polls.apps.PollsConfig', # <- この行を追加 ] #...
どのような値をセットするかわからない場合には、アプリケーションのフォルダ中のapps.py
内を見ればわかります。今回の場合にはPollsConfig
クラスが定義されています。
これでプロジェクトはpollsアプリケーションを認識してくれます。コマンドラインで
$ python manage.py makemigrations polls
と入力します。すると
Migrations for 'polls': polls/migrations/0001_initial.py - Create model Choice - Create model Question - Add field question to choice
と表示されて「Question
モデル」、「Choice
モデル」、そして「questionとchoiceを対応させるフィールド」が作成されます。
makemigrations
だけでは実は、models.py
の内容をデータベースへ登録するための中間ファイルしか作成していません(これをマイグレーションファイルと呼びます)。実際にデータベースに登録するにはもうひと手間必要で、
$ python manage.py migrate
これで完了です。
管理ユーザーを作成する
作ったモデルを管理するために、管理ユーザーを作ります。これには、コマンドラインで
$ python manage.py createsuperuser
とします。好きなユーザー名とメールアドレス、パスワードを設定します。終わったらpython manage.py runserver
でサーバーを起動して
http://127.0.0.1:8000/adminにアクセスすると、次のようなログイン画面が現れます。
設定したユーザー名とパスワードでログインすると、管理者画面に移行します。
ここまでの状態では、QuestionやChoiceといったモデルが管理者画面に反映されていません。反映させるためには、pollsディレクトリのadmin.py
を編集します。
polls/admin.py
from django.contrib import admin from .models import Question admin.site.register(Question)
再び管理者画面を見ると、ちゃんとpollsアプリケーションのモデルが登録されています。
QuestionのところをクリックするとQuestionが登録できます。試しに「What's up?」というquestion textで、時刻はtoday, nowを押してsaveするとQuestionが登録できます。しかし、Questionの一覧に今登録したものが登録されています...しかし表示が「Question object (1)」となっていて何のことかさっぱりわかりません。オブジェクトの表示方法を変えるのはクラスに__str__
を定義すればよいのでした。Pythonの特殊メソッドの使い方がよく分からない場合には以下のサイトをどうぞ
基本的な特殊メソッドと__str__ - Python学習講座
では、models.py
の編集をします。
polls/models.py
from django.db import models # Create your models here. class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def __str__(self): # <- 特殊メソッド__str__を定義、question_textが表示されるようにする return self.question_text class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) def __str__(self): # <- ついでにChoiceのほうも return self.choice_text
これで、Question一覧の画面(
http://127.0.0.1:8000/admin/polls/question/
)にはWhat's upと、qustion_textが表示されるようになっています。
今回はここまでです。この記事で書いたことは
- データベースのマイグレーション方法
- モデルの作り方とデータベースへの登録方法
- 管理ユーザーの設定
でした。次回はこのモデルを使って実際のページの編集を行っていきます。