Closed11

Djangoのチュートリアルをなぞってみる その3:データベース

suzuki-navisuzuki-navi

DBの接続設定はmysite/settings.pyに書いてある。

# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}
suzuki-navisuzuki-navi

mysite/settings.pyにある以下の記述は、Djangoのこのprojectに初めからインストールされているappがリストしてある。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

このappの中にはDBのテーブルを必要とするものがある。SQLiteのファイルは0バイトの状態で存在している。

$ ll db.sqlite3
-rw-r--r-- 1 ubuntu ubuntu 0 2023-08-05 10:37:42 db.sqlite3

以下のコマンドで、各appが必要とするテーブル作成をする。

$ 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 auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

$ ll db.sqlite3
-rw-r--r-- 1 ubuntu ubuntu 131072 2023-08-05 12:45:34 db.sqlite3
suzuki-navisuzuki-navi

sqlite3コマンドをUbuntu 22.04にインストールしてみる。

$ sudo apt install -y sqlite3

$ sqlite3 --version
3.40.1 2022-12-28 14:03:47 df5c253c0b3dd24916e4ec7cf77d3db5294cc9fd45ae7b9c5e82ad8197f3alt1
suzuki-navisuzuki-navi

SQLiteに作成されたテーブルを見てみる。

$ sqlite3 db.sqlite3
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  auth_user_user_permissions
auth_group_permissions      django_admin_log
auth_permission             django_content_type
auth_user                   django_migrations
auth_user_groups            django_session

テーブルの中身。ほとんどはまだレコードが1つもないが一部のテーブルはレコードが存在する。

sqlite> select * from auth_group;

sqlite> select * from auth_user;

sqlite> select * from django_admin_log;

sqlite> select * from django_content_type;
1|admin|logentry
2|auth|permission
3|auth|group
4|auth|user
5|contenttypes|contenttype
6|sessions|session

sqlite> select * from django_migrations;
1|contenttypes|0001_initial|2023-08-05 03:45:34.406722
2|auth|0001_initial|2023-08-05 03:45:34.438475
3|admin|0001_initial|2023-08-05 03:45:34.472886
4|admin|0002_logentry_remove_auto_add|2023-08-05 03:45:34.487529
5|admin|0003_logentry_add_action_flag_choices|2023-08-05 03:45:34.501505
6|contenttypes|0002_remove_content_type_name|2023-08-05 03:45:34.519439
7|auth|0002_alter_permission_name_max_length|2023-08-05 03:45:34.535129
8|auth|0003_alter_user_email_max_length|2023-08-05 03:45:34.549934
9|auth|0004_alter_user_username_opts|2023-08-05 03:45:34.564350
10|auth|0005_alter_user_last_login_null|2023-08-05 03:45:34.578646
11|auth|0006_require_contenttypes_0002|2023-08-05 03:45:34.589921
12|auth|0007_alter_validators_add_error_messages|2023-08-05 03:45:34.601402
13|auth|0008_alter_user_username_max_length|2023-08-05 03:45:34.615729
14|auth|0009_alter_user_last_name_max_length|2023-08-05 03:45:34.629335
15|auth|0010_alter_group_name_max_length|2023-08-05 03:45:34.646827
16|auth|0011_update_proxy_permissions|2023-08-05 03:45:34.659136
17|auth|0012_alter_user_first_name_max_length|2023-08-05 03:45:34.672031
18|sessions|0001_initial|2023-08-05 03:45:34.695287

sqlite> select * from django_session;
suzuki-navisuzuki-navi

モデルを作る。次のように編集する。

diff --git a/mysite/mysite/settings.py b/mysite/mysite/settings.py
index 96f9eca..1a08a1b 100644
--- a/mysite/mysite/settings.py
+++ b/mysite/mysite/settings.py
@@ -37,6 +37,7 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
+    'polls.apps.PollsConfig',
 ]

 MIDDLEWARE = [
diff --git a/mysite/polls/models.py b/mysite/polls/models.py
index 71a8362..dc981e8 100644
--- a/mysite/polls/models.py
+++ b/mysite/polls/models.py
@@ -1,3 +1,10 @@
 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")
+
+class Choice(models.Model):
+    question = models.ForeignKey(Question, on_delete=models.CASCADE)
+    choice_text = models.CharField(max_length=200)
+    votes = models.IntegerField(default=0)

polls/apps.pyPollsConfig クラスが定義してある。settings.pyにある'polls.apps.PollsConfig'とはこれのことだろう。

polls/apps.py
from django.apps import AppConfig

class PollsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'polls'
suzuki-navisuzuki-navi

python manage.py makemigrations pollsコマンドでマイグレーションスクリプトを作成。python manage.py migrateの前にこれをやらないといけないのか。

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

Pythonスクリプトが1つ生成される。

polls/migrations/0001_initial.py
# Generated by Django 4.2.4 on 2023-08-05 04:12

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Question',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('question_text', models.CharField(max_length=200)),
                ('pub_date', models.DateTimeField(verbose_name='date published')),
            ],
        ),
        migrations.CreateModel(
            name='Choice',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('choice_text', models.CharField(max_length=200)),
                ('votes', models.IntegerField(default=0)),
                ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.question')),
            ],
        ),
    ]

テーブルにはidカラムが勝手にできるようだ。

suzuki-navisuzuki-navi

マイグレーションスクリプトを実行する。

$ python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" bigint NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;

何番のマイグレーションまで実行済みかのステータスは保持していないのだろうか。。。

suzuki-navisuzuki-navi

python manage.py sqlmigrateコマンドはSQLを表示するだけで、SQLiteへの実際の変更処理は行わない。プレビュー目的。だからステータスは関係なかった。

実際に変更処理するには以下のコマンド。

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

マイグレーションのステータスはdjango_migrationsテーブルに保存されているようだ。

$ sqlite3 db.sqlite3
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.
sqlite> select * from django_migrations;
1|contenttypes|0001_initial|2023-08-05 03:45:34.406722
2|auth|0001_initial|2023-08-05 03:45:34.438475
3|admin|0001_initial|2023-08-05 03:45:34.472886
4|admin|0002_logentry_remove_auto_add|2023-08-05 03:45:34.487529
5|admin|0003_logentry_add_action_flag_choices|2023-08-05 03:45:34.501505
6|contenttypes|0002_remove_content_type_name|2023-08-05 03:45:34.519439
7|auth|0002_alter_permission_name_max_length|2023-08-05 03:45:34.535129
8|auth|0003_alter_user_email_max_length|2023-08-05 03:45:34.549934
9|auth|0004_alter_user_username_opts|2023-08-05 03:45:34.564350
10|auth|0005_alter_user_last_login_null|2023-08-05 03:45:34.578646
11|auth|0006_require_contenttypes_0002|2023-08-05 03:45:34.589921
12|auth|0007_alter_validators_add_error_messages|2023-08-05 03:45:34.601402
13|auth|0008_alter_user_username_max_length|2023-08-05 03:45:34.615729
14|auth|0009_alter_user_last_name_max_length|2023-08-05 03:45:34.629335
15|auth|0010_alter_group_name_max_length|2023-08-05 03:45:34.646827
16|auth|0011_update_proxy_permissions|2023-08-05 03:45:34.659136
17|auth|0012_alter_user_first_name_max_length|2023-08-05 03:45:34.672031
18|sessions|0001_initial|2023-08-05 03:45:34.695287
19|polls|0001_initial|2023-08-05 06:13:45.283897

テーブルが増えていた。

$ sqlite3 db.sqlite3
SQLite version 3.40.1 2022-12-28 14:03:47
Enter ".help" for usage hints.
sqlite> .tables
auth_group                  django_admin_log
auth_group_permissions      django_content_type
auth_permission             django_migrations
auth_user                   django_session
auth_user_groups            polls_choice
auth_user_user_permissions  polls_question
suzuki-navisuzuki-navi

Pythonでモデルを定義してからDBのテーブルに反映するまでの流れ

  • python manage.py makemigrations polls
  • python manage.py sqlmigrate polls 0001
  • python manage.py migrate
このスクラップは2023/08/05にクローズされました