Skip to content

Djangoでウェブアプリを作る(8) – モデルを有効にする

前回の記事:
Djangoでウェブアプリを作る(7)

今回参照する公式チュートリアル:
https://docs.djangoproject.com/ja/3.2/intro/tutorial02

今回は、モデルを有効にする・・ということで、モデル作成後に、まだ、何かいじらなければならないようだ。

スポンサードリンク

SQL文は書かなくてよいらしい・・

前述のようなほんのわずかなコードをモデルに書くだけで、Django はたくさんの情報を知れます。このコードを使って、 Django は:・アプリケーションのデータベーススキーマを作成 (CREATE TABLE 文を実行) できます。
・Question や Choice オブジェクトに Python からアクセスするためのデータベー ス API を作成できます。

うーむ・・わずかなコードを書くだけでDjangoが察してくれるというのは、何となく分かるが・・

データベースの「スキーマ」とは ” データベースの構造を表現する設計図 ” ・・つまり、データベースを作る時にわざわざSQL文を書く必要が無い、ということのようだ。

データベースAPIを作成できる・・

SQLiteでデータベースを操作する時はSQL文を書く必要があるが、大抵は、DatabaseManagerクラスのような形でAPIを自前で書いていた。その部分をDjangoが自動で作ってくれるということだな。

そこは自動でやってくれないのか・・

でもその前に、pollsアプリケーションをインストールしたことをプロジェクトに教えてやる必要があります。

えーと・・ pollsアプリケーションを作成しただけでは、Django側は、アプリを認識できないということなのか?

アプリケーションをプロジェクトに含めるには、構成クラスへの参照を INSTALLED_APPS 設定に追加する必要があります。

・・・INSTALLED_APPSというのはどこだ? ああ、mysite/settings.py の中にある。

mysite/settings.py

# Application definition

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

ここに構成クラスの参照を追加・・・何、構成クラスって?

チュートリアルのコードには、一行追加されてるな・・・

mysite/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',
]

” polls.apps.PollsConfig ” が構成クラスということか?

PollsConfig クラスは、 polls/apps.py にあるので、ドットつなぎのパスは ‘polls.apps.PollsConfig’ となります。

polls/apps.pyって初めて開くな。

あ、自動でPollsConfigクラスが定義されてる。中身は意味不明だが・・・

polls/apps.py

from django.apps import AppConfig

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

とりあえず、プロジェクト内でアプリケーションを作成すると、この構成クラスとやらが、apps.pyに自動で定義される。それを手動でsettings.py の ” INSTALLED_APPS ” に追加しろ・・・ということでいいのでしょうか?

どうせなら、ここまで自動化出来んのか?

コマンド ” makemigrations “

さて、これでpollsアプリケーションが認識できるらしい。

プロンプトで以下のコマンドを実行。

python manage.py makemigrations polls

実行後、次のような表示が・・

C:\django_project\mysite>python manage.py makemigrations polls

Migrations for 'polls':
  polls\migrations\0001_initial.py
    - Create model Question
    - Create model Choice

mysite/polls/migrationsフォルダ内に0001_initial.pyが作成されている。

中身はこんな感じだ。

mysite/polls/migrations/001_initial.py

# Generated by Django 3.2.6 on 2021-08-22 08:34

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')),
            ],
        ),
    ]

何となく、SQL文に渡して、データベースにテーブルを作ってるような感じだな・・

マイグレーション(migration)を直訳すると「移転」を意味する。

Djangoでは、モデル(データベースの設計図)に変更があった場合、マイグレーションという単位で変更履歴を保存するらしい。

データベースの設計は、そんなに変更する機会は無いような気もするが・・・何か、使う場面があるのだろうか?

コマンド ” sqlmigrate “

マイグレーションがどんなSQLを実行するのか見てみましょう。 sqlmigrate コマンドはマイグレーションの名前を引数にとってSQLを返します:

マイグレーションが、どうやってデータベースにアクセスしているか、変換後のSQL文を見ていこう。次のコマンドを実行してみる。

python manage.py sqlmigrate polls 0001

ああ、マイグレーションがSQL文に変換された。

なるほど、実際はこんな感じでSQL文に変換されてデータベースにテーブルを定義しているのだな。

C:\django_project\mysite>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;

あれ・・・チュートリアルの実行例とちょっと違うな・・

因みに、チュートリアルでは次のような感じだ。

BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL,
    "question_id" integer NOT NULL
);
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");

COMMIT;

チュートリアルのドキュメントバージョンは3.2、Djangoのバージョン3.2.6なので、どちらも最新のはずだが・・・

ここは、なぜこうなっているのか不明。あまり、深入りすると足踏み状態になりそうだ。エラーが出ているわけではないので、とりあえずスルーしておこう。

コマンド ” migrate “

モデル(データベース設計)を変更する時は、次の3ステップが必要のようだ。

1. モデルを変更する。

2. ” python manage.py makemigrations ” を実行し、マイグレーションを作成。

3. ” python manage.py migrate ” を実行し、マイグレーションを適用する。

ここで注意点。チュートリアルでは、サラッと次のような一文がある。

sqlmigrate コマンドは実際にはデータベースにマイグレーションを実行しません。ただ、Djangoが必要としているSQLが何であるかをスクリーンに表示するだけです。

” sqlmigrate “ と ” migrate ” という二つのコマンドがあり、モデルを実際に適応するのは、” migrate ” の方だ。(これを見過ごして次回ミスを犯すことに・・)

migrateコマンドはすべての適用されていないマイグレーションを捕捉してデータベースに対してそれを実行します。

では、コマンドプロンプトでmigrateコマンドを実行して、定義したモデルをデータベースに反映させておこう。

C:\django_project\mysite>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, 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 polls.0001_initial... OK
  Applying sessions.0001_initial... OK

C:\django_project\mysite>

これで、いいんだよな?

ああ、確かにデータベースファイル(db.sqlite3)が生成されてるな。

ところで、.idea__pycache__ というフォルダがいつの間にかあるんだが、これ何だろう?

.ideaフォルダは、Pychameで今回のプロジェクトを読み込んだ時に自動生成されたようだ。今回は開発環境は使わないので削除しておく。

__pychache__は、コンパイルされたコードがまとめられている。毎回、実行時に再コンパイルしなくてもよいように勝手に作るらしい。削除してもまた勝手に生成されるだろう。

独習Python 山田 祥寛 (著)
スポンサードリンク:Amazon

この記事をシェア

Comments are closed, but trackbacks and pingbacks are open.