kb84tkhrのブログ

何を書こうか考え中です あ、あと組織とは関係ないってやつです 個人的なやつ

Djangoチュートリアル (2) モデル

はじめての Django アプリ作成、その2

mysite/settings.py を眺める
データベースやアプリの設定があるけど今はいじらなくてよい

データベースをマイグレートする

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
...
  Applying sessions.0001_initial... OK
$ ls
db.sqlite3  manage.py  mysite  polls

sqlite3のファイルができてる

$ sqlite3 db.sqlite3 
sqlite> .schema
CREATE TABLE IF NOT EXISTS "django_migrations" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "app" varchar(255) NOT NULL, "name" varchar(255) NOT NULL, "applied" datetime NOT NULL);
CREATE TABLE sqlite_sequence(name,seq);
...
CREATE INDEX "django_session_expire_date_a5c62663" ON "django_session" ("expire_date");
sqlite> .quite

モデルの作成

モデルは、手持ちのデータに対する唯一の決定的なソースです。 ... Django のモデルの目的は、ただ一つの場所でデータモデルを定義し、そこから自動的に色々なものを派生させることにあります。
マイグレーションは完全にモデルのファイルから生成されます。

polls/models.py

from django.db import models

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = medels.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)

Field インスタンスそれぞれの名前(例: question_text や pub_date)は、機械可読なフィールド名です。このフィールド名はPythonコードで使うとともに、データベースも列の名前として使うことになります。

このへん、どういう仕組みになってんだろうね
さっきやった、マイグレートの作業のときになにかやってるんだろうけど

Field の最初の位置引数には、オプションとして人間可読なフィールド名も指定できます。このフィールド名は Django の二つの内省機能で使う他、ドキュメントとしての役割も果たします。

内省ってのはリフレクションの訳かな
用語としてそういう訳し方もある?
確かに内省と言えなくもない

mysite/settings.pyにpollsアプリが追加されたことを反映する
さっきURLを追加したけどあれだけじゃ足りないのか

INSTALLED_APPS = [
    'polls.apps.PollsConfig', #ここ
    'django.contrib.admin',
    ...
    'django.contrib.staticfiles',
]

そしてマイグレーションを作成
マイグレーションマイグレーション言うけどマイグレーションとは何か

$ python manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Choice
    - Create model Question
    - Add field question to choice

polls/migrations/0001_initial.py というファイルができてて
中身はもっと生っぽいスキーマ定義のコード
これを実行するとスキーマが定義されるんだろう

sqlmigrateというサブコマンドでSQLにして見ることができるらしい

$ python manage.py sqlmigrate polls 0001
BEGIN;
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL);
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
ALTER TABLE "polls_choice" RENAME TO "polls_choice__old";
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id"));
INSERT INTO "polls_choice" ("id", "choice_text", "votes", "question_id") SELECT "id", "choice_text", "votes", NULL FROM "polls_choice__old";
DROP TABLE "polls_choice__old";
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;

なるほど
だいたいわかった

これでmigrateすると新たなテーブルができる

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

マイグレーションはとても強力なツールであり、プロジェクトの発展に合わせて、モデルを変更し続けていくことができます。データベースやテーブルを削除して作り直す必要はありません - マイグレーションは、データを失うことなしにデータベースをライブでアップグレードするよう特化しています。

model.pyを変更したらmakemigrationsしてmigrateする
モデルを変更したらマイグレーションを作ってマイグレートする
次はデータベースに差分を適用するコードが0002の下にできるんだろうな
だいたいわかった

マイグレーションの作成と適用のコマンドが分割されている理由は、マイグレーションバージョン管理システムにコミットし、アプリとともに配布するためです。

なんかそういうの聞いたことある
Database as Codeだったか
スキーマ変更をロールバックするスクリプトもできてたりするのかな