導入
このチュートリアルでは、保存するブログアプリケーションのデータのフィールドと動作を定義するDjangoモデルを作成します。これらのモデルは、Djangoアプリケーションのデータをデータベースにマッピングします。Djangoは、このモデルに基づいて、オブジェクトリレーショナルマッピング(ORM)API(「モデル」と呼ばれる)を通じてデータベーステーブルを生成します。.
前提条件
このチュートリアルは、Django 開発シリーズの一部であり、そのシリーズの続きです。.
このシリーズをフォローしていない場合は、次のことを前提としています。
- Django バージョン 4 以降がインストールされています。.
- Django アプリケーションをデータベースに接続しました。.
- Unix ベースのオペレーティング システムを使用しています。テストに使用したシステムである Ubuntu 22.04 クラウド サーバーが望ましいです。.
このチュートリアルでは主に Django モデルを扱っているため、設定が異なっていても同様に実行できる可能性があります。.
ステップ1 – Djangoアプリケーションを作成する
Django のモジュール化の理念に従うために、ブログ Web サイトの作成に必要なすべてのファイルを含む Django アプリケーションをプロジェクト内に作成します。.
PythonとDjangoで作業を始める際は、必ずPython仮想環境を有効化し、アプリケーションのルートディレクトリに移動する必要があります。このシリーズを既にご覧いただいている方は、以下のコマンドを入力することで実行できます。.
cd ~/my_blog_app
. env/bin/activate
cd blogr code... */そこから、次のコマンドを実行しましょう:
python manage.py startapp blogsiteこのプログラムは、ディレクトリとともにブログ サイトを作成します。.
チュートリアル シリーズのこの時点では、プロジェクトのディレクトリ構造は次のようになります。
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.pyこのチュートリアルで重点的に取り上げるファイルは、サイトのブログ ディレクトリにある models.py ファイルです。.
ステップ2 – 投稿テンプレートを追加する
まず、models.pyファイルを開いて編集し、Postモデルを生成するコードを追加します。Postモデルには、以下のデータベースフィールドが含まれます。
- TITLE – ブログ投稿のタイトル。.
- スラッグ – Web ページの有効な URL が保存および生成される場所。.
- コンテンツ – ブログ投稿のテキストコンテンツ。.
- create_on – 投稿が作成された日付。.
- AUTHOR – 投稿を書いた人。.
次に、models.py ファイルがあるディレクトリに移動します。.
cd ~/my_blog_app/blog/blogsitecat コマンドを使用して、ターミナルにファイルの内容を表示します。.
cat models.pyファイルには、モデルをインポートする次のコードと、この models.py ファイルに何が含まれるかを説明するコメントが含まれている必要があります。.
from django.db import models
# Create your models here.お好みのテキストエディタを使って、models.pyファイルに以下のコードを追加してください。ここではnanoエディタを使用しますが、お好みのエディタをお使いください。.
nano models.pyこのファイルにはAPIモデルをインポートするコードが既に追加されているので、下のコメントを削除して進めることができます。次に、文字列からスラッグを生成するslugify、認証用のDjangoユーザー、そしてURL作成の柔軟性を高めるためにdjango.urlsからスラッグを生成するslugifyをインポートします。.
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse次に、モデルクラス(Post)に、データベースフィールド(title、slug、content、created_on、author)を持つクラスメソッドを追加します。これらのメソッドは、import文の下に追加してください。.
...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()次に、URLを生成する関数と投稿を保存する関数を追加します。これは、投稿ごとに固有のリンクを作成するため、非常に重要です。.
...
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)次に、モデルに投稿をどのように並べ替えてウェブページ上に表示するかを伝える必要があります。このロジックは、ネストされたメタクラスに追加します。メタクラスには通常、データベースフィールドの定義とは関係のない、他の重要なモデルロジックが含まれます。.
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title最後に、このファイルにCommentモデルを追加します。これは、models.Modelsというシグネチャを持つCommentという別のクラスを追加し、以下のデータベースフィールドを定義することを意味します。
- NAME – コメントを送信した人の名前。.
- EMAIL – コメントを送信した人のメールアドレス。.
- TEXT – コメント自体のテキスト。.
- POST – コメントが作成された投稿。.
- create_on – コメントが作成された日時。.
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)これで models.py は完成です。models.py ファイルが以下の内容と一致していることを確認してください。
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)必ずファイルを保存して閉じてください。nanoをお使いの場合は、CtrlキーとXキー、Yキー、Enterキーの順に押してください。.
models.py ファイルを実行すると、settings.py ファイルを更新できます。.
ステップ3 – 設定を更新する
アプリケーションにモデルを追加したので、追加したブログサイトアプリケーションの存在をプロジェクトに知らせる必要があります。これは、settings.py の INSTALLED_APPS セクションに追加することで行います。.
settings.py があるディレクトリに移動します。.
cd ~/my_blog_app/blog/blogここから、たとえばnanoを使用してsettings.pyファイルを開きます。.
nano settings.pyファイルを開いて、以下に示すように、ファイルの INSTALLED_APPS セクションにサイトのブログ アプリを追加します。.
# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]サイトのブログ アプリケーションを追加したら、ファイルを保存して終了できます。.
現時点では、これらの変更の実装を進める準備ができています。.
ステップ4 – 移行を実行する
Post モデルと Comment モデルを追加したら、次のステップではこれらの変更を適用して、MySQL データベース スキーマがそれらを認識し、必要なテーブルを作成するようにします。.
まず、makemigrationsコマンドを使って、モデルの変更を個別のマイグレーションファイルにまとめる必要があります。これらのファイルは、Gitなどのバージョン管理システムにおけるコミットに似ています。.
さて、 ~/my_blog_app/blog/blogsite/migrations に移動して ls を実行すると、__init__.py ファイルが1つしかないことがわかります。これは、マイグレーションを追加すると変わります。.
次のように、 cd を使用してブログ ディレクトリに移動します。
cd ~/my_blog_app/blog次に、manager.py で makemigrations コマンドを実行します。.
python manage.py makemigrationsすると、ターミナル ウィンドウに次の出力が表示されます。
Output
Migrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment
/~/my_blog_app/blog/blogsite/migrations にアクセスした時に、__init__.py ファイルしかなかったのを覚えていますか?今、そのディレクトリに戻ると、__pycache__ と 0001_initial.py という2つの項目が追加されていることがわかります。0001_initial.py ファイルは、makemigrations を実行したときに自動的に作成されました。makemigrations を実行するたびに、同様のファイルが作成されます。.
ファイルの内容を読み取る場合は、ファイルがあるディレクトリから 0001_initial.py を実行するだけです。.
次に、~/my_blog_app/blog に移動します。
cd ~/my_blog_app/blogマイグレーションファイルを作成したので、これらのファイルに記載されている変更を migrate コマンドを使用してデータベースに適用する必要があります。まずは、 showmigrations コマンドを使用して、現在存在するマイグレーションを確認しましょう。.
python manage.py showmigrationsOutput
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
blogsite
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initialPost モデルと Comment モデルで作成した 0001_initial の移行を除き、すべての移行がチェックされていることがわかります。.
では、以下のコマンドを使って、マイグレーション完了後に実行されるSQL文を確認してみましょう。このコマンドは、マイグレーション名とマイグレーションタイトルを引数として受け取ります。
python manage.py sqlmigrate blogsite 0001_initial以下に、舞台裏で実際に実行されている SQL クエリを示します。.
Output
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);次に、移行を実行して MySQL データベースに適用してみましょう。.
python manage.py migrate次のような出力が得られます。
Output
Operations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OKこれで移行が正常に適用されました。.
Django のドキュメントに記載されているように、バックエンドとして MySQL を使用して Django を移行する場合は 3 つの注意点があることに留意することが重要です。.
- スキーマ変更操作に関するトランザクションはサポートされていません。つまり、移行が失敗した場合、手動で変更内容を選択して再度移行を実行する必要があります。失敗した移行に変更を加える前の時点にロールバックする方法はありません。.
- MySQLはほとんどのスキーマ変更操作において、テーブルを完全に書き換えます。最悪の場合、実行時間はテーブル内の列の追加または削除の行数に比例します。Djangoのドキュメントによると、この処理には100万行あたり1分ほどかかる場合があります。.
- MySQLでは、列名、テーブル名、インデックス名の長さに若干の制限があります。また、すべての列とインデックスボリュームの合計サイズにも制限があります。他のバックエンドではDjangoで設定されたより高い制限をサポートできるものもありますが、MySQLバックエンドでは同じインデックスを作成することはできません。.
Django で使用することを検討しているデータベースについては、それぞれの長所と短所を必ず比較検討してください。.
ステップ5 – データベーススキーマを確認する
移行が完了したら、Django モデルを通じて作成した MySQL テーブルが正常に生成されたことを確認する必要があります。.
これを行うには、ターミナルで次のコマンドを実行して MySQL にログインします。.
mysql blog_data -u djangouser次に、blog_dataデータベースを選択します。使用しているデータベースがわからない場合は、SHOW DATABASESですべてのデータベースを表示できます。SQLでは
USE blog_data;次に、次のコマンドを入力してテーブルを表示します。.
SHOW TABLES;この SQL クエリにより次のことが明らかになります。
Output
+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.01 sec)テーブルにはblogsite_commentとblogsite_postが含まれています。これらは私たちが作成したモデルです。定義したフィールドが含まれていることを確認しましょう。.
DESCRIBE blogsite_comment;Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)DESCRIBE blogsite_post;Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)Django モデルの移行からデータベース テーブルが正常に生成されたことを確認しました。.
CTRL + D で MySQL を閉じ、Python 環境を終了する準備ができたら、disable コマンドを実行できます。
deactivate開発環境を無効にすると、ターミナルのコマンドラインに戻ります。.
結果
このチュートリアルでは、ブログウェブアプリケーションの基本機能のためのモデルを追加することに成功しました。モデルのコーディング方法、マイグレーションの仕組み、そしてDjangoモデルを実際のMySQLデータベーステーブルに変換するプロセスを学びました。.









