前回、djangoでプロジェクト作成&hello worldでプロジェクトを作成してhelloworldページを表示するところまでやりました。
今回はモデルを定義してDBを使うところまでやります。
引き続き公式チュートリアルのほぼコピペです。
プロジェクトの設定ファイルであるmysite/settings.pyにDB設定を書いていきます。ここではpostgreSQLを使います。
と思ったのですが、実際のサービスデプロイをdockerでやろうと思っているのでdocker-compose&djangoで環境を作ることにします。
ちょうどいいドキュメントを見つけたのでこれに従ってやってみます。
djangoのプロジェクト直下(manage.pyがあるディレクトリ)にDockerfile, requirements.txt, docker-compose.ymlをそれぞれ作成します。
Dockerfile
FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/
requirements.txt
Django>=3.0,<4.0
psycopg2-binary>=2.8
docker-compose.yml
version: '3'
services:
db:
image: postgres
restart: always
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
web:
build: .
restart: always
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
DB設定
DB接続のための設定をします。PostgreSQLの場合です。
プロジェクト作成時に自動生成されたsettings.pyを編集します。DATABASES
という箇所があるのでそこを書き換えます。デフォルトではsqlite3を使う設定になっています。
# postgresを使うための設定
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
このDB名・ユーザー名・パスワードは、docker-compose内でdbイメージ作成時に環境変数で設定した値を書きます。
ホストのところが'db'
となっていますがこれは、docker-composeのイメージ名を指定することでそのホストにアクセスできるようになっているためです(確かdocker-composeがイメージ名をホスト名として解釈してくれる)。
これでdocker-compose up
すると、前回作ったhelloworldページへhttp://localhost:8000/polls/でアクセスできるようになります。とりあえずdocker-compose化ができました。
(DBは設定だけした状態なのでまだアプリ内では使っていませんが、DB名やユーザー名・パスワード等を正しく設定していないと起動時にエラーが出るはずです)
以降、manage.pyを使うコマンドなどターミナル上で実行するコマンドは基本的にdocker-compose経由で実行していきます。
DBを使う
setttings.pyのINSTALLED_APPS
の値をみるとわかりますが、デフォルトでadmin, auth, contenttypesなどと言った「アプリ」が入っています。
これらの中にDBを必要とするものがあるので(adminやauthなど?)、マイグレーションをする必要があります。
$ docker-compose run web python manage.py migrate
このコマンドは、INSTALLED_APP
に定義されているアプリに必要なDBテーブルを作成してくれます。その時にsettings.pyのDB設定を利用し、また各アプリで定義されているDBマイグレーションを利用するようです。
モデル定義
今度は自分でモデルを定義してみます。django.db.models.Modelのサブクラスとしてモデルを定義すると、そこからDBスキーマが自動で生成されます。
pollsアプリのモデルを定義するので、polls/models.pyを編集します。空のファイルがすでにあるはずです。
models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
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):
return self.choice_text
ここで各モデルに__str__()
を定義していますが、これは対話環境で各レコードの中身をさらっと確認する時に便利ですし、自動生成されるadminでも利用されるため定義しておいた方が良いようです。
マイグレーション
このモデルに対応するDBテーブルを自動生成するためには、INSTALLED_APPS
にpollsアプリを追加する必要があります。ここに追加するパスはpollsアプリのコンフィグクラスへのパスなので、今回の場合はpolls/apps.py内のPollsConfig
というクラスを以下のように追記します。
settings.py
INSTALLED_APPS = [
'polls.apps.PollsConfig', # この一行追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
で、以下のコマンドでdjangoにモデルの変更を知らせるとマイグレーションファイルが生成されます。
$ docker-compose run web python manage.py makemigrations polls
マイグレーションの内容と生成ファイルパスが以下のように標準出力されます。
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
このマイグレーションファイルから生成されるSQLが気になる場合は以下のコマンドで確認することができます。これは指定されたマイグレーションファイルからSQLを生成するコマンドです。
(確認する必要がなければ実行する必要はありません)
$ docker-compose run web python manage.py sqlmigrate polls 0001
以下のコマンドでプロジェクトの構成チェックができますが、これはDBに関する不具合も検証してくれるようです(どんな不具合が起き得るのか、どんな不具合を検出できるのか不明)。
$ docker-compose run web python manage.py check
マイグレーションをするには以下のコマンドを実行します。
$ docker-compose run web python manage.py migrate
対話環境でモデルを使って遊ぶ
以下のコマンドでモデルを使って遊ぶことができます。DBの読み書きもちゃんとできます。
$ docker-compose run web python manage.py shell
以下のような感じです。
>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet []>
>>> from django.utils import timezone
>>> q = Question(question_text="What's up?", pub_date=timezone.now())
>>> q.save()
>>> q.id
1
>>> q.question_text
"What's up?"