Djangoモデルを作成する方法
序章
前のチュートリアル「Djangoアプリを作成してデータベースに接続する方法」では、MySQLデータベースを作成する方法、Djangoアプリケーションを作成して起動する方法、およびデータベースに接続する方法について説明しました。 MySQLデータベース。
このチュートリアルでは、保存するブログアプリケーションデータのフィールドと動作を定義するDjangoモデルを作成します。 これらのモデルは、Djangoアプリケーションからのデータをデータベースにマップします。 これは、Djangoが「モデル」と呼ばれるオブジェクトリレーショナルマッピング(ORM)APIを介してデータベーステーブルを生成するために使用するものです。
前提条件
このチュートリアルは、 Django開発シリーズの一部であり、そのシリーズの続きです。
このシリーズに従わなかった場合は、次のことを前提としています。
- Djangoバージョン3以降がインストールされています。
- Djangoアプリをデータベースに接続しました。 MySQLを使用しています。この接続は、Djangoシリーズのパート2「Djangoアプリを作成してデータベースに接続する方法」に従うことで実現できます。
- Unixベースのオペレーティングシステム、できればUbuntu 20.04クラウドサーバーを使用しています。これは、私たちがテストしたシステムです。 同様の環境でDjangoをセットアップする場合は、チュートリアル「 Ubuntu20.04にDjangoをインストールして開発環境をセットアップする方法」を参照してください。
このチュートリアルは主にDjangoモデルを扱っているため、セットアップが多少異なっていても従うことができる場合があります。
ステップ1—Djangoアプリケーションを作成する
モジュール性のDjango哲学と一致するように、ブログWebサイトの作成に必要なすべてのファイルを含むDjangoアプリをプロジェクト内に作成します。
PythonとDjangoで作業を開始するときはいつでも、Python仮想環境をアクティブにして、アプリのルートディレクトリに移動する必要があります。 シリーズをフォローしている場合は、次のように入力することでこれを実現できます。
- cd ~/my_blog_app
- . env/bin/activate
- cd blog
そこから、次のコマンドを実行してみましょう。
- python manage.py startapp blogsite
これにより、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
このチュートリアルで焦点を当てるファイルは、blogsite
ディレクトリにあるmodels.py
ファイルです。
ステップ2—投稿モデルを追加する
まず、models.py
ファイルを開いて編集し、Post
モデルを生成するためのコードが含まれるようにする必要があります。 Post
モデルには、次のデータベースフィールドが含まれています。
title
—ブログ投稿のタイトル。slug
—Webページの有効なURLが保存および生成される場所。content
—ブログ投稿のテキストコンテンツ。created_on
—投稿が作成された日付。author
—投稿を書いた人。
次に、models.py
ファイルが含まれているディレクトリに移動します。
- cd ~/my_blog_app/blog/blogsite
cat
コマンドを使用して、端末のファイルの内容を表示します。
- cat models.py
このファイルには、モデルをインポートする次のコードと、このmodels.py
ファイルに何を配置するかを説明するコメントが含まれている必要があります。
from django.db import models
# Create your models here.
お気に入りのテキストエディタを使用して、models.py
ファイルに次のコードを追加します。 テキストエディタとしてnano
を使用しますが、お好きなものを使用できます。
- nano models.py
このファイル内に、モデルAPIをインポートするためのコードがすでに追加されています。先に進んで、次のコメントを削除できます。 次に、文字列からスラッグを生成するためのslugify
、認証用のDjangoのUser
、django.urls
からreverse
をインポートして、URL作成の柔軟性を高めます。
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
。 これらをインポートステートメントの下に追加します。
...
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)
次に、投稿をどのように注文し、Webページに表示するかをモデルに指示する必要があります。 このためのロジックは、ネストされた内部Meta
クラスに追加されます。 Meta
クラスには通常、データベースフィールドの定義に関係のない他の重要なモデルロジックが含まれています。
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
最後に、Comment
モデルをこのファイルに追加します。 これには、Comment
という名前の別のクラスを追加し、その署名にmodels.Models
を含め、次のデータベースフィールドを定義する必要があります。
name
—コメントを投稿した人の名前。email
—コメントを投稿した人のメールアドレス。text
—コメント自体のテキスト。post
—コメントが付けられた投稿。created_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—設定を更新する
アプリケーションにモデルを追加したので、追加したばかりのblogsite
アプリの存在をプロジェクトに通知する必要があります。 これを行うには、settings.py
のINSTALLED_APPS
セクションに追加します。
settings.py
が存在するディレクトリに移動します。
- cd ~/my_blog_app/blog/blog
ここから、たとえばnanoを使用してsettings.py
ファイルを開きます。
- nano settings.py
ファイルを開いた状態で、以下に示すように、blogsite
アプリをファイルの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',
]
blogsite
アプリを追加すると、ファイルを保存して終了できます。
この時点で、これらの変更を適用する準備が整いました。
ステップ4—移行を行う
モデルPost
とComment
を追加したら、次のステップはこれらの変更を適用して、MySQL
データベーススキーマがそれらを認識し、必要なテーブルを作成するようにします。
まず、コマンドmakemigrations
を使用して、モデルの変更を個々の移行ファイルにパッケージ化する必要があります。 これらのファイルは、Gitなどのバージョン管理システムのcommits
のファイルに似ています。
ここで、~/my_blog_app/blog/blogsite/migrations
に移動して、ls
を実行すると、__init__.py
ファイルしかないことに気付くでしょう。 移行を追加すると、これは変更されます。
次のように、cd
を使用してブログディレクトリに移動します。
- cd ~/my_blog_app/blog
次に、manage.py
でmakemigrations
コマンドを実行します。
- python manage.py makemigrations
次に、ターミナルウィンドウに次の出力が表示されます。
OutputMigrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model 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
に移動します。
- cd ~/my_blog_app/blog
移行ファイルを作成したので、コマンドmigrate
を使用して、これらのファイルに記述されている変更をデータベースに適用する必要があります。 ただし、最初にshowmigrations
コマンドを使用して、現在どの移行が存在するかを確認しましょう。
- python manage.py showmigrations
Outputadmin
[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_initial
モデルPost
および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
次の出力を受け取ります。
OutputOperations 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にログインします。 前のチュートリアルで作成したdjangouser
を使用します。
- mysql blog_data -u djangouser
次に、データベースblog_data
を選択します。 使用しているデータベースがわからない場合は、SQLでSHOW DATABASES;
を使用してすべてのデータベースを表示できます。
- 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環境を終了する準備ができたら、deactivate
コマンドを実行できます。
- deactivate
プログラミング環境を非アクティブ化すると、ターミナルコマンドプロンプトに戻ります。
結論
このチュートリアルでは、ブログWebアプリケーションの基本機能のモデルを正常に追加しました。 models
のコーディング方法、migrations
の動作、およびDjangomodels
を実際のMySQL
データベーステーブルに変換するプロセスを学習しました。