Djangoモデルの作成方法

イントロダクションを日本語で表現すると、「導入」となります。

前のチュートリアル、「Djangoアプリの作成とデータベースへの接続方法」では、MySQLデータベースの作成方法、Djangoアプリの作成と起動方法、そしてMySQLデータベースへの接続方法について説明しました。

このチュートリアルでは、保存するブログアプリケーションのデータのフィールドと振る舞いを定義するDjangoのモデルを作成します。これらのモデルは、Djangoアプリケーションからデータベースにデータをマッピングします。これはDjangoがオブジェクトリレーショナルマッピング(ORM)APIを介してデータベーステーブルを生成するために使用するもので、「モデル」と呼ばれています。

前提条件

このチュートリアルはDjango開発シリーズの一部であり、そのシリーズの続きです。

このシリーズを追っかけていない場合、以下の仮定をしています。

  • You have Django version 4 or higher installed.
  • You have connected your Django app to a database. We are using MySQL, and you can achieve this connection by following part two of the Django series, “How To Create a Django App and Connect it to a Database.”
  • You are working with a Unix-based operating system, preferably an Ubuntu 22.04 cloud server as this is the system we have tested on. If you would like to set up Django on a similar environment, please refer to our tutorial, “How To Install Django and Set Up a Development Environment on Ubuntu 22.04.”

このチュートリアルは主にDjangoのモデルに関連していますので、セットアップが少し異なっていても、ある程度の理解ができるかもしれません。

ステップ1 — Djangoアプリケーションを作成する

Djangoのモジュール性の原則に従い、ブログウェブサイトを作成するために、プロジェクト内にDjangoアプリを作成します。このアプリには、必要なすべてのファイルが含まれます。

PythonとDjangoの作業を始めるときは、Pythonの仮想環境をアクティベートし、アプリのルートディレクトリに移動する必要があります。シリーズに沿って進めてきた場合、以下のように入力することでこれを実現できます。

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

 

そこから、このコマンドを実行しましょう。

  1. 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

このチュートリアルでは、焦点を当てるファイルは、blogsiteディレクトリ内にあるmodels.pyファイルになります。

ステップ2 – 投稿モデルを追加してください。

まず、models.pyファイルを開いて編集する必要があります。このファイルには、投稿モデルの生成コードが含まれている必要があります。投稿モデルには、以下のデータベースフィールドが含まれています。

  • title — The title of the blog post.
  • slug — Where valid URLs are stored and generated for web pages.
  • content — The textual content of the blog post.
  • created_on — The date on which the post was created.
  • author — The person who has written the post.

今、models.pyファイルが含まれているディレクトリに移動してください。

  1. cd ~/my_blog_app/blog/blogsite

 

ターミナルでファイルの内容を表示するために、catコマンドを使用してください。

  1. cat models.py

 

ファイルには、モデルをインポートする以下のコードが必要です。また、このmodels.pyファイルには何を配置するかを説明するコメントも含めてください。

モデル.py
from django.db import models

# Create your models here.

お気に入りのテキストエディタを使用して、以下のコードをmodels.pyファイルに追加してください。この例ではテキストエディタとしてnanoを使用していますが、お好きなものを使用しても結構です。

  1. nano models.py

 

このファイル内には、モデルAPIをインポートするためのコードがすでに追加されていますので、続くコメントを削除しても構いません。それから、文字列からスラッグを生成するためにslugifyをインポートし、認証のためにDjangoのUserをインポートし、URLをより柔軟に作成するためにdjango.urlsのreverseをインポートします。

モデル.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

その後、Postというモデルクラスにクラスメソッドを追加します。以下のデータベースフィールドを持ちます:タイトル、スラッグ、コンテンツ、作成日時、著者。これらをImport文の下に追加してください。

モデル.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の生成機能と投稿の保存機能を追加します。これは重要です。なぜなら、ユニークな投稿に対応するユニークなリンクを作成するからです。

モデルズ.py
...
    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)

今、私たちはモデルに投稿がどのように順序付けられ、ウェブページ上で表示されるかを伝える必要があります。そのために、ネストされた内部のMetaクラスにロジックを追加します。Metaクラスには、一般にデータベースのフィールドの定義とは関係ない他の重要なモデルロジックが含まれます。

モデル.py
...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

最終的に、このファイルにはCommentモデルを追加します。これには、モデルにmodels.Modelsを含むCommentという別のクラスを追加し、次のデータベースフィールドを定義する必要があります。

  • name — The name of the person posting the comment.
  • email — The email address of the person posting the comment.
  • text — The text of the comment itself.
  • post — The post with which the comment was made.
  • created_on — The time the comment was created.
モデル.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
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が存在するディレクトリに移動してください。

  1. cd ~/my_blog_app/blog/blog

 

ここから、例えばnanoを使って、settings.pyファイルを開いてください。

  1. nano settings.py

 

ファイルを開いたら、以下に示すように、ファイルの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',
]

ブログサイトアプリを追加すると、ファイルを保存して終了することができます。

この時点で、私たちはこれらの変更を適用する準備ができています。

ステップ4 — マイグレーションを作成する

私たちのモデル「Post」と「Comment」を追加したら、次のステップはこれらの変更を適用し、MySQLデータベースのスキーマがそれらを認識し、必要なテーブルを作成することです。

最初に、モデルの変更を個別のマイグレーションファイルにパッケージ化する必要があります。この作業は、Gitなどのバージョン管理システムのコミットに似ています。

今、~/my_blog_app/blog/blogsite/migrationsに移動し、lsコマンドを実行すると、__init__.pyファイルしか見つかりません。この状態は、マイグレーションを追加すると変わります。

cdを使ってブログディレクトリに移動してください。

  1. cd ~/my_blog_app/blog

 

manage.pyに対して、makemigrationsコマンドを実行してください。

  1. 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。0001_initial.py ファイルは、makemigrations を実行した際に自動生成されました。同様のファイルは、makemigrations を実行するたびに生成されます。

もしファイルの内容を確認したい場合は、そのディレクトリ内から0001_initial.pyを実行しないでください。

今、~/my_blog_app/blogに移動してください。

  1. cd ~/my_blog_app/blog

 

私たちはマイグレーションファイルを作成したので、データベースにこれらのファイルで説明された変更を適用するために、マイグレーションコマンドを使用する必要があります。しかし、最初に、showmigrationsコマンドを使用して現在存在するマイグレーションを確認しましょう。

  1. python manage.py showmigrations

 

Output

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_initial

0001_initialという名前でPostとCommentのモデルを作成したマイグレーションを除き、すべてのマイグレーションがチェックされていることに気づくでしょう。

以下のコマンドを使用して、マイグレーションを行った後に実行されるSQL文を確認しましょう。マイグレーションとマイグレーションのタイトルを引数として受け取ります。

  1. 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データベースに適用されるように移行を実行しましょう。

  1. python manage.py migrate

 

以下の出力を受け取ります。 (Shimon no shutsuryoku o uketorimasu.)

Output

Operations to perform: Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations: Applying blogsite.0001_initial… OK

現在、マイグレーションが正常に適用されました。

Djangoのドキュメントに述べられている通り、MySQLをバックエンドとした場合、Djangoのマイグレーションには注意点が3つあります。

  • Lack of support for transactions around schema alteration operations. In other words, if a migration fails to apply successfully, you will have to manually unpick the changes you’ve made in order to attempt another migration. It is not possible to rollback, to an earlier point, before any changes were made in the failed migration.
  • For most schema alteration operations, MySQL will fully rewrite tables. In the worst case, the time complexity will be proportional to the number of rows in the table to add or remove columns. According to the Django documentation, this could be as slow as one minute per million rows.
  • In MySQL, there are small limits on name lengths for columns, tables and indices. There is also a limit on the combined size of all columns and index covers. While some other backends can support higher limits created in Django, the same indices will fail to be created with a MySQL backend in place.

Djangoを使用するための各データベースについて、利点と欠点を吟味することを忘れずに考慮してください。

「ステップ 5 — データベースのスキーマを確認します。

移行が完了したら、Djangoモデルを通じて作成したMySQLテーブルの正常な生成を確認する必要があります。

前のチュートリアルで作成したdjangouserを使用してMySQLにログインするために、ターミナルで以下のコマンドを実行してください。

  1. mysql blog_data -u djangouser

 

今、私たちのデータベースblog_dataを選択してください。もし使用しているデータベースがわからない場合は、SQLでSHOW DATABASES;を使ってすべてのデータベースを表示できます。

  1. USE blog_data;

 

次のコマンドを入力して、テーブルを表示してください。

  1. 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)

テーブルの中には、ブログサイトのコメントとブログサイトの投稿が含まれています。これらは私たち自身で作成したモデルです。定義したフィールドが含まれているかを確認しましょう。

  1. 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)

  1. 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モデル移行からデータベーステーブルが正常に生成されたことを確認しました。

MySQLを終了するには、CTRL + Dで終了することができます。Pythonの環境を終了する準備ができたら、deactivateコマンドを実行することができます。

  1. deactivate

 

プログラミング環境の無効化により、ターミナルのコマンドプロンプトに戻ります。

結論

このチュートリアルでは、ブログWebアプリケーションの基本機能のためのモデルを正常に追加しました。モデルのコーディング方法、マイグレーションの動作、そしてDjangoモデルを実際のMySQLデータベーステーブルに変換するプロセスについて学びました。

コメントを残す 0

Your email address will not be published. Required fields are marked *