前書き
前のチュートリアルでは、「https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect-it-to-a-database[Djangoアプリの作成方法] MySQLデータベースの作成方法、Djangoアプリケーションの作成と起動方法、およびMySQLデータベースへの接続方法について説明しました。
このチュートリアルでは、保存するブログアプリケーションデータのフィールドと動作を定義するDjangomodelsを作成します。 これらのモデルは、Djangoアプリケーションのデータをデータベースにマッピングします。 Djangoは、「モデル」と呼ばれるオブジェクトリレーショナルマッピング(ORM)APIを介してデータベーステーブルを生成するために使用します。
前提条件
MySQLをUbuntu 16.04サーバーにインストールし、Djangoアプリケーションとデータベース接続をセットアップする必要があります。 まだこれを行っていない場合は、Djangoシリーズのパート2、「https://www.digitalocean.com/community/tutorials/how-to-create-a-django-app-and-connect-」を参照してください。 it-to-a-database [Djangoアプリを作成してデータベースに接続する方法]
[[step-1 -—- create-django-application]] ==ステップ1—Djangoアプリケーションを作成する
モジュール性のDjango哲学を維持するために、ブログWebサイトの作成に必要なすべてのファイルを含むDjangoアプリをプロジェクト内に作成します。
最初にPython仮想環境をアクティブにします。
cd ~/my_blog_app
. env/bin/activate
cd blog
そこから、このコマンドを実行しましょう:
python manage.py startapp blogsite
この時点で、プロジェクトに次のディレクトリ構造が作成されます。
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
このチュートリアルで焦点を当てるファイルは、models.py
ファイルになります。
[[step-2 -—- add-the-posts-model]] ==ステップ2—投稿モデルを追加する
まず、Post
モデルを生成するためのコードが含まれるように、models.py
ファイルを開いて編集する必要があります。 Post
モデルには、次のデータベースフィールドが含まれています。
-
title
—ブログ投稿のタイトル。 -
slug
—Webページの有効なURLが保存および生成される場所。 -
content
—ブログ投稿のテキストコンテンツ。 -
created_on
—投稿が作成された日付。 -
author
—投稿を書いた人。
ここで、ディレクトリをmodels.py
ファイルが含まれている場所に変更します。
cd ~/my_blog_app/blog/blogsite
cat
コマンドを使用して、端末内のファイルの内容を表示します。
cat models.py
このファイルには、モデルをインポートする次のコードと、このmodels.py
ファイルに何を配置するかを説明するコメントが含まれている必要があります。
models.py
from django.db import models
# Create your models here.
お気に入りのテキストエディタまたはIDEを使用して、次のコードをmodels.py
ファイルに追加します。 テキストエディタとしてnano
を使用します。 しかし、あなたが好きなものを使用することは大歓迎です。
nano models.py
このファイル内には、モデルAPIをインポートするコードがすでに追加されています。先に進み、続くコメントを削除できます。 次に、文字列からスラッグを生成するためのslugify
をインポートし、次のように認証のためにDjangoのUser
をインポートします。
models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
次に、Post
を呼び出すモデルクラスに、次のデータベースフィールド、title
、slug
、content
、created_on
、およびauthor
。
models.py
...
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を生成する機能と、投稿を保存する機能を追加します。 これは、私たちのユニークな投稿に一致するユニークなリンクを作成するため、重要です。
models.py
...
@models.permalink
def get_absolute_url(self):
return ('blog_post_detail', (),
{
'slug': self.slug,
})
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
次に、投稿がどのように順序付けられ、Webページに表示されるかをモデルに伝える必要があります。 このためのロジックは、ネストされた内部Meta
クラスに追加されます。 Meta
クラスには通常、データベースフィールドの定義に関係のない他の重要なモデルロジックが含まれています。
models.py
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
最後に、Comment
モデルをこのファイルに追加します。 これには、署名にmodels.Models
が含まれ、次のデータベースフィールドが定義されているComment
という名前の別のクラスを追加することが含まれます。
-
name
—コメントを投稿した人の名前。 -
email
—コメントを投稿した人のメールアドレス。 -
text
—コメント自体のテキスト。 -
post
—コメントが作成された投稿。 -
created_on
—コメントが作成された時刻。
models.py
...
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
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()
@models.permalink
def get_absolute_url(self):
return ('blog_post_detail', (),
{
'slug': 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)
必ずファイルを保存して閉じてください。
models.py
ファイルを設定したら、settings.py
ファイルの更新に進むことができます。
[[step-3 -—- update-settings]] ==ステップ3—設定を更新します
アプリケーションにモデルを追加したので、追加したばかりのblogsite
アプリの存在をプロジェクトに通知する必要があります。 これを行うには、settings.py
のINSTALLED_APPS
セクションに追加します。
settings.py
が存在するディレクトリに移動します。
cd ~/my_blog_app/blog/blog
ここから、コマンドnano settings.py
を使用して、たとえばnanoでsettings.py
ファイルを開きます。
ファイルを開いた状態で、次に示すように、blogsite
アプリをファイルのINSTALLED_APPS
セクションに追加します。
settings.py
# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
blogsite
アプリを追加すると、ファイルを保存して終了できます。
この時点で、これらの変更を適用する準備が整いました。
[[step-4 -—- make-migrations]] ==ステップ4—移行を行う
モデルPost
とComment
を追加したら、次のステップはこれらの変更を適用して、MySQL
データベーススキーマがそれらを認識し、必要なテーブルを作成するようにすることです。
blog_data
データベースにすでに存在するテーブルを見てみましょう。
これを行うには、MySQLサーバーにログインする必要があります。
[.note]#Note:この例では、パスワードなしでユーザー名root
を使用しますが、MySQL用に設定したユーザー名とパスワードを使用する必要があります。
#
mysql blog_data -u root
SHOW DATABASES;
コマンドを入力すると、次のように表示されます。
Output+--------------------+
| Database |
+--------------------+
| information_schema |
| blog_data |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
blog_data
データベースを調べて、既存のテーブルがある場合はそれを表示します。
USE blog_data;
次に、blog_data
データベースに存在するテーブルを一覧表示します。
SHOW TABLES;
OutputEmpty set (0.00 sec)
現在、まだ移行を行っていないため、テーブルは表示されません。 ただし、移行を行うと、Djangoによって生成されたテーブルが表示されます。
次に、models.py
で行った変更を適用する移行を行います。
CTRL
+D
でMySQLを閉じます。
まず、コマンドmakemigrations
を使用して、モデルの変更を個々の移行ファイルにパッケージ化する必要があります。 これらのファイルは、git
のようなバージョン管理システムのcommits
のファイルに似ています。
ここで、~/my_blog_app/blog/blogsite/migrations
に移動してls
を実行すると、__init__.py
ファイルしかないことに気付くでしょう。 これは、移行を追加すると変更されます。
次のように、cd
を使用してブログディレクトリに移動します。
cd ~/my_blog_app/blog
python manage.py makemigrations
ターミナルウィンドウに次の出力が表示されます。
OutputMigrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Comment
- Create model Post
- Add field post to comment
/~/my_blog_app/blog/blogsite/migrations
に移動したときに、__init__.py
ファイルしかなかったことを覚えていますか? cd
をそのディレクトリに戻すと、__pycache__
と0001_initial.py
の2つが追加されていることがわかります。 makemigrations
を実行すると、0001_initial.py
ファイルが自動的に生成されました。 makemigrations
を実行するたびに、同様のファイルが生成されます。
ファイルの内容を確認したい場合は、less 0001_initial.py
を実行します。
次に、~/my_blog_app/blog
に移動します。
移行ファイルを作成したので、コマンドmigrate
を使用して、これらのファイルに記述されている変更をデータベースに適用する必要があります。 ただし、最初に、showmigrations
コマンドを使用して、現在どのような移行が存在するかを確認しましょう。
python manage.py showmigrations
Outputadmin
[ ] 0001_initial
[ ] 0002_logentry_remove_auto_add
auth
[ ] 0001_initial
[ ] 0002_alter_permission_name_max_length
[ ] 0003_alter_user_email_max_length
[ ] 0004_alter_user_username_opts
[ ] 0005_alter_user_last_login_null
[ ] 0006_require_contenttypes_0002
[ ] 0007_alter_validators_add_error_messages
[ ] 0008_alter_user_username_max_length
[ ] 0009_alter_user_last_name_max_length
blogsite
[ ] 0001_initial
contenttypes
[ ] 0001_initial
[ ] 0002_remove_content_type_name
sessions
[ ] 0001_initial
blogsite
に追加した移行に気付くでしょう。これには、モデルPost
とComment
の移行0001_initial
が含まれています。
次のコマンドを使用して、移行を行った後に実行されるSQL
ステートメントを見てみましょう。 移行と移行のタイトルを引数として受け取ります。
python manage.py sqlmigrate blogsite 0001_initial
以下に示すように、これは実際に行われているSQLクエリです。
BEGIN;
--
-- 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);
--
-- 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);
--
-- Add field post to comment
--
ALTER TABLE `blogsite_comment` ADD COLUMN `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`);
COMMIT;
次に、MySQLデータベースに適用されるように移行を実行します。
python manage.py migrate
次の出力が表示されます。
OutputOperations to perform:
Apply all migrations: admin, auth, blogsite, 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 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 blogsite.0001_initial... OK
Applying sessions.0001_initial... OK
これで移行が正常に適用されました。
Djangoのドキュメントに記載されているように、MySQLをバックエンドとして使用したDjangoの移行には3つの注意事項があることに留意することが重要です。
-
スキーマ変更操作に関するトランザクションのサポートの欠如。 つまり、移行が正常に適用されない場合、別の移行を試行するには、行った変更を手動で選択解除する必要があります。 失敗した移行で変更が行われる前に、以前の時点にロールバックすることはできません。
-
ほとんどのスキーマ変更操作では、MySQLはテーブルを完全に書き換えます。 最悪の場合、時間の複雑さは、列を追加または削除するテーブルの行数に比例します。 Djangoのドキュメントによると、これは100万行につき1分程度の遅い可能性があります。
-
MySQLでは、列、テーブル、インデックスの名前の長さに小さな制限があります。 また、すべての列とインデックスカバーの合計サイズにも制限があります。 他の一部のバックエンドはDjangoで作成されたより高い制限をサポートできますが、MySQLバックエンドを適切に配置すると同じインデックスを作成できません。
Djangoでの使用を検討している各データベースについて、それぞれの長所と短所を必ず検討してください。
[[step-5 -—- verify-database-schema]] ==ステップ5—データベーススキーマを確認する
移行が完了したら、Djangoモデルを介して作成したMySQLテーブルが正常に生成されたことを確認する必要があります。
これを行うには、ターミナルで次のコマンドを実行してMySQLにログインします。
mysql blog_data -u root
存在するデータベースを表示します。
SHOW DATABASES;
データベースblog_data
を選択します。
USE blog_data;
次に、次のコマンドを入力してテーブルを表示します。
SHOW TABLES;
以下が表示されるはずです。
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 |
+----------------------------+
blogsite_comment
とblogsite_post
が表示されます。 これらは私たちが自分たちで作ったモデルです。 定義したフィールドが含まれていることを検証しましょう。
DESCRIBE blogsite_comment;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | 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(11) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
DESCRIBE blogsite_post;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | 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.01 sec)
Djangoモデルの移行からデータベーステーブルが正常に生成されたことを確認しました。
CTRL
+D
を使用してMySQLを終了でき、Python環境を終了する準備ができたら、deactivate
コマンドを実行できます。
deactivate
プログラミング環境を非アクティブ化すると、ターミナルコマンドプロンプトに戻ります。
結論
このチュートリアルでは、ブログWebアプリケーションの基本機能のモデルを正常に追加しました。 models
をコーディングする方法、migrations
がどのように機能するか、Djangomodels
を実際のMySQL
データベーステーブルに変換するプロセスを学習しました。