ユーニックス総合研究所

  • home
  • archives
  • python-django-linebbs-create-models

Django入門: モデルの作成 ~ 簡単な一行掲示板アプリを作る その8【Windows10】

  • 作成日: 2020-10-20
  • 更新日: 2023-12-26
  • カテゴリ: Django

はじめに

この記事は「Djangoで一行掲示板を作る」というシリーズの記事です。

前回までにDjangoのプロジェクトとアプリを作成し、ビューからテンプレートを描画し、DBのマイグレーションを行い、動作テストを行いました。

今回から実際に掲示板のためのモデルを定義してマイグレーションを行っていきます。

前提としてOSはWindowsでコマンドプロンプトを使います。
仮想環境を使っているのでvenv\Scripts\activateをアクティベートしています。
仮想環境については第一回の記事をご覧ください。
また初期位置として、プロジェクト内のmanage.pyのあるディレクトリに移動してある前提です。

モデルはいつ作るのか?

ところでモデルはいつ作るべきなのでしょうか?
基本的にはモデル作成の優先度は高いのが普通です。
つまり、プロジェクトの初期の段階でモデルを作るのがよくある方法です。

今回のシリーズではルート情報からビュー、そしてテンプレート、DBの初期マイグレーションという風に進んでいますが、別にこれはモデルの作成を一番最初にやってもかまいません。
このシリーズでは最初に「Hello, World!」を表示するためにこの手順で進んでますが、実際の開発では臨機応変に好きなところから開発を進めます。

また、開発を進めるとモデルが必要になる時がやってきますので、その時に作成するというのもありです。

掲示板のモデルの要件

今回作っているのは一行掲示板です。
ということは掲示板の利用者の投稿内容を表示できるようにする必要があります。
利用者の投稿内容はDBに保存する必要があるので、この「投稿内容」を表現するモデルが必要になることがわかります。

今回はこの「投稿内容」をPostというモデルを作成して表現したいと思います。
Postには投稿内容を表すcontentというフィールドを作ります。
フィールドとは、モデル内に複数作れるデータを入れる箱のことですね。
Postは変数と言うよりはデータのまとまりを表すものです。
そのまとまりの中にフィールドという実際のデータを入れる箱があるというイメージです。

モデル「Post」の作成

ではmanage.pyのあるディレクトリから作業を開始します。
モデルはアプリのディレクトリ以下のmodels.pymodels\ディレクトリ以下に定義するのが一般的です。
あくまで一般的なので他の場所にモデルを定義することも可能です。

bbs\models.pyをエディタで開くと↓のような内容になっています。

from django.db import models  

# Create your models here.  

「Create your models here.」、つまり「あなたのモデルをここに作ってね」と書いてあります。
それからfrom django.db import modelsはモデルを作成するのに必要なモジュールをインポートしています。
ではさっそくこのファイル内にモデルを作りましょう。

from django.db import models  


class Post(models.Model):  
    """  
    掲示板への投稿内容  
    """  
    pass  

↑のようにモデルはクラスとして定義します。
クラスはmodels.Modelを継承している必要があります。
クラスの名前は加工されてDB内のテーブルの名前になります。
たとえばアプリ名が「bbs」であれば↑のモデルは「bbs_post」という名前でテーブルが定義されます。
この名前は開発者が変更することも可能です。

さらにモデルPostにフィールドを追加します。

from django.db import models  


class Post(models.Model):  
    """  
    掲示板への投稿内容  
    """  
    content = models.CharField(max_length=140, help_text='掲示板の投稿内容')  

モデル内のフィールドは↑のようにクラスの属性として定義します。
↓を詳しく見てみます。

content = models.CharField(max_length=140, help_text='掲示板の投稿内容')  

Djangoにはモデルのフィールドを定義するためのクラスが多数用意されています。
models.CharFieldというのはそのクラスの内の1つです。
このクラスは文字列を扱うためのフィールドです。
引数のmax_lengthはこのフィールドに格納できる最大文字列数を指定します。↑の例では140になっています。
help_textは管理ページに表示するテキストで、サイト管理者にフィールドの役割を説明するための属性です。

これでモデルの定義は完了しました。
簡単ですね。

マイグレーションの実行

モデルを定義したら次はモデルのマイグレーションを行います。
今回作ったモデルは私たちのオリジナルのモデルなので、マイグレーションファイルはまだ作成されていません。
よって最初にmakemigrationsを実行してマイグレーションファイルを作成する必要があります。

manage.pyのあるディレクトリから↓のコマンドを実行すると↓のようなログが表示されます。

> python manage.py makemigrations  
Migrations for 'bbs':  
  bbs\migrations\0001_initial.py  
    - Create model Post  

↑のログを見ると「bbs\migrations\0001_initial.py」というマイグレーションファイルが作成されているのがわかります。
このマイグレーションファイルをエディタで開いてみると↓のようになっています。

# Generated by Django 3.1.1 on 2020-09-21 20:06  

from django.db import migrations, models  


class Migration(migrations.Migration):  

    initial = True  

    dependencies = [  
    ]  

    operations = [  
        migrations.CreateModel(  
            name='Post',  
            fields=[  
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),  
                ('content', models.CharField(help_text='掲示板のポスト内容', max_length=140)),  
            ],  
        ),  
    ]  

クラスMigrationがマイグレーションを実際に実行するスクリプトとなるクラスです。
operationsというリストがありますが、ここにDBを操作するためのオペレーションが入ります。
↑の例ではmigrations.CreateModelというのがそのオペレーションです。

このマイグレーションファイルですが、マイグレーションでエラーが起きた場合などに開発者が直接編集することがあります。

ではマイグレーションファイルを作成したのでマイグレーションを実行しましょう。

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

python manage.py migrateでマイグレーションを実行すると↑のように「bbs.0001_initial... OK」と表示されます。
先ほどのマイグレーションファイルの実行が成功したようです。

では試しにもう一回マイグレーションを実行してみてください。

> python manage.py migrate  
Operations to perform:  
  Apply all migrations: admin, auth, bbs, contenttypes, sessions  
Running migrations:  
  No migrations to apply.  

今度は↑のように表示されます。
「No migrations to apply.」、つまり「適用するマイグレーションはありません」と表示されます。
このようにDjangoでは実行したマイグレーションを記録して管理しています。
そのため一度実行したマイグレーションは再度実行されないようになっています。
この記録はDB内のdjango_migrationsというテーブルで管理されています。

DBの中身を見てみる

ここからは余談ですが、DBの中身を見てみたいと思います。
ただしこれは、環境にsqlite3が入っている人限定の余談です。
環境でsqlite3が使える場合はmanage.pyのあるディレクトリから↓のようにコマンドを実行すると、sqlite3db.sqlite3をオープンすることが出来ます。

> sqlite3 db.sqlite  
SQLite version 3.11.0 2016-02-15 17:29:24  
Enter ".help" for usage hints.  
sqlite>  

sqlite3のコマンドラインから↓のようにコマンドを実行すると、DB内のテーブルの一覧を表示できます。

sqlite> .tables  
auth_group                  bbs_post  
auth_group_permissions      django_admin_log  
auth_permission             django_content_type  
auth_user                   django_migrations  
auth_user_groups            django_session  
auth_user_user_permissions  

↑の内、bbs_postというのが今回作成したモデルです。
django_migrationsのレコードを見てみます。

sqlite> select * from django_migrations;  
1|contenttypes|0001_initial|2020-09-20 21:02:09.629999  
2|auth|0001_initial|2020-09-20 21:02:09.712794  
3|admin|0001_initial|2020-09-20 21:02:09.805690  
4|admin|0002_logentry_remove_auto_add|2020-09-20 21:02:09.899446  
5|admin|0003_logentry_add_action_flag_choices|2020-09-20 21:02:10.006855  
6|contenttypes|0002_remove_content_type_name|2020-09-20 21:02:10.096771  
7|auth|0002_alter_permission_name_max_length|2020-09-20 21:02:10.182166  
8|auth|0003_alter_user_email_max_length|2020-09-20 21:02:10.281426  
9|auth|0004_alter_user_username_opts|2020-09-20 21:02:10.382155  
10|auth|0005_alter_user_last_login_null|2020-09-20 21:02:10.483390  
11|auth|0006_require_contenttypes_0002|2020-09-20 21:02:10.566693  
12|auth|0007_alter_validators_add_error_messages|2020-09-20 21:02:10.665567  
13|auth|0008_alter_user_username_max_length|2020-09-20 21:02:10.757945  
14|auth|0009_alter_user_last_name_max_length|2020-09-20 21:02:10.848351  
15|auth|0010_alter_group_name_max_length|2020-09-20 21:02:10.964376  
16|auth|0011_update_proxy_permissions|2020-09-20 21:02:11.054930  
17|auth|0012_alter_user_first_name_max_length|2020-09-20 21:02:11.140816  
18|sessions|0001_initial|2020-09-20 21:02:11.227002  
19|bbs|0001_initial|2020-09-21 20:12:04.857470  

↑の↓の行を見るとわかりますが、しっかりと今回のマイグレーションが記録されています。

19|bbs|0001_initial|2020-09-21 20:12:04.857470  

次にbbs_postのテーブルの定義を見てみます。

sqlite> .schema bbs_post  
CREATE TABLE "bbs_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" varchar(140) NOT NULL);  

↑を見ると、idcontentが定義されているのがわかります。
idですが、Djangoのモデルは自動でidというフィールドをテーブルに定義します。このフィールドはテーブルのプライマリーキーとして利用されます。

おわりに

今回は掲示板用のモデルを作成しました。
次回から今回作ったモデルを使ったコードを書いていきたいと思います。

🦊 < 来週へ続く