【Django】モデルとは?基本からmodels.pyの記述方法まで徹底解説!

Django

Djangoのmodels.pyは、データベースとやりとりするために必要で、Djangoフレームワークの中核を成す部分です。本記事では、Djangoのモデルの基本から操作方法までをわかりやすく解説します。

1. はじめに

models.pyは、アプリケーションで保持したいデータが必要とするフィールド(サイズや型など)その動作を定義します。
一般的に、各モデルは単一のデータベースのテーブルに対応付けられます。

まず簡単な例を確認しましょう。(ドキュメントより引用)
次の例では 、models.pyでfirst_name と last_name を持つ Person というモデルをクラスとして定義しています。

# models.py
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

上記のPersonモデルを定義することで、djangoは以下のようなデータベースのテーブルを作成してくれます。

CREATE TABLE myapp_person (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

2. Djangoモデル(models.py)の基本

models.pyの役割について理解したところで、もう少し詳しくみていきましょう。

2-1. models.py の記述方法について

タイトルやコンテンツ、作成日時を保持する、簡単なブログのモデルを以下のように定義する例で考えます。

ポイントをいくつか説明します。

django.dbには、データベース操作に関連するモジュールが格納されています。
そこからDjangoのデータベースの操作に使うためのクラスやメソッドを提供する、modelsをインポートしています。

②Blogクラスは、①のmodels内でインポートしたモジュールで定義されている、Modelを基底クラスとしています。ここがよく分からない場合は、「Python 継承」でググって下さい。

③Fieldクラスのインスタンスを作成します。フィールドの設定箇所と考えて良いです。「どのような設定をするのか」は長くなるので次の章に記載します。
①②④はお作法的に書いても問題ないですが、③はmodels.pyを書くうえで肝となります。

④オブジェクトが文字列として表示される際にどのような文字列を返すかを決定します。
Blogオブジェクトを表示したときに、そのブログのタイトルが表示されるようになります。

2-2. フィールド(項目)の種類

「2-1. models.pyの記述方法について」で説明した、③のフィールドについて、どのようなものがあるか、主要なところを説明します。詳細が気になる方はリファレンスをご覧ください。

フィールドの種類

CharField: 文字列
 class CharField(max_length=None**options)  

   小 – 大サイズの文字列のフィールド。多量のテキストを扱うときはTextFieldを使う。このフィールドのデフォルトのフォームウィジェットはTextInput。


TextField: 長いテキスト
 class TextField(**options)  

   多量のテキストのフィールド。max_length 属性を指定した場合、自動生成されたフォームフィールドのTextareaウィジェット内で反映されるが、モデルやデータベースのレベルでは関係ない。


IntegerField
 class IntegerField(**options) 

  -2147483648 から 2147483647 までの整数。 MinValueValidatorと MaxValueValidator によって、入力値の検証が行われる。


FloatField: 浮動小数点数
 class FloatField(**options)

  float インスタンスによって表される Python の浮動小数点数。


DateTimeField: 日付と時刻
 class DateTimeField(auto_now=Falseauto_now_add=False**options)

  Python で datetime.datetime インスタンスによって表される日付と時刻。DataFieldと同じくいくつかの追加的な引数を持つ。


BooleanField: 真偽値(True or False)
 class BooleanField(**options)

   Field.default が定義されていないときの BooleanField のデフォルト値は None。

2-3. フィールドオプション

上記で紹介したフィールドはそれぞれ、あらかじめ定められたフィールド特有の引数を受け取ります。

例えば、CharField はそのデータを保持するためにデータベース上に定義される VARCHAR 領域の長さを定義する引数 max_length を必要とします。

一方で、全てのフィールドの型で利用できる共通の引数も存在します(**options)。
ここでは、特に頻繁に使われるものについて簡単な概要を説明します。(詳しくみたい方はこちら)

フィールドオプション

■null

True の場合、Django は空の値をデータベース内に NULL として保持します。デフォルトは False です


■blank

True の場合、フィールドはブランクになることが許容されます。デフォルトは False です。

<nullとblankについて>

blank がバリデーション由来である一方、 null はデータベース由来です。
あるフィールドが blank=True であれば、フォームのバリデーションは空の値の入力を許容します。あるフィールドが blank=False の場合は、そのフィールドへの入力は必須となります。


■primary_key

True の場合、設定したフィールドはそのモデルの主キーとなります。

<主キーについて>

定義したモデル内でどのフィールドに対しても primary_key=True が設定されなかった場合、Django は自動的に IntegerField を追加します。つまり、その主キーに対するデフォルトの動作を変更する必要がない場合は、どのフィールドに対しても primary_key=True を設定する必要がありません。


■unique

True の場合、そのフィールドはテーブル上で一意となる制約を受けます。

3. モデルの利用とマイグレーション

一度モデルを定義した後は、Django にこれらのモデルを利用するということを知らせる必要があります。

そのために、設定ファイル(settings.py)を編集して、設定値 INSTALLED_APPS に定義した models.py を含むモジュール名を追加します。

たとえば、アプリケーションのモデルが myapp.models モジュール内に存在する場合、INSTALLED_APPS の部分を次のように定義します。

# settings.py
INSTALLED_APPS = [
    # ...
    "myapp",
    # ...
]

また、モデルを変更した際にその変更をデータベースに反映させるためにマイグレーションを使用します。マイグレーションの流れは次の通りです。

(1)モデルの変更を加えた後、以下コマンドでマイグレーションファイルを生成します。

$ python manage.py makemigrations

(2)データベースに反映させます。

$ python manage.py migrate

4. Djangoモデルの操作方法

ここからは、modelの操作方法について解説します。

4-1. オブジェクトの作成

オブジェクトを生成するためには、作成するモデルのクラスにキーワード引数を渡してインスタンス化し、そのデータをデータベースに保存するためにsave()を呼び出します。

以下はモデルがDjangoアプリ blog 内の models.py ファイルに存在する場合の例です。

from blog.models import Blog

b = Blog(name="Beatles Blog", tagline="All the latest Beatles news.")
b.save()

内部的には INSERT SQL 文が処理されています。また、明示的にsave()を呼ぶまで Django はデータベースを操作しません。

4-2. データの変更

すでにデータベースに保存されている Blog インスタンス b5 がある場合、この例ではその名前を変更し、データベース内のレコードを更新します。

b5.name = "New name"
b5.save()

内部的には UPDATE SQL 文が処理されます。また、明示的にsave()を呼ぶまで Django はデータベースを操作しません。

4-3. データの取得

データベースからオブジェクトを取得する際は、モデルクラスのManegerからQuerySet として取り出します。

フィルターとなるパラメータを用いてクエリの検索結果(=QuerySet)を絞り込みます。
SQL 文で考えると、 QuerySet は SELECT 句、フィルタは WHERE や LIMIT のような絞り込みに対応しています。

また、インスタンスからはManegerにはアクセスすることができません。

>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name="Foo", tagline="Bar")
>>> b.objects
Traceback:
    ...
AttributeError: "Manager isn't accessible via Blog instances."

上記のコード例は、インスタンスからManagerにアクセスできないことを示しています。
これは “テーブル水準” の処理と “レコード水準” の処理とで責任を明確に分離するためだそうです。

全てのデータを取得する

全データを取得するには、 Managerのall()メソッドを使います。

all_entries = Blog.objects.all()

all()メソッドは、データベース内のすべてのオブジェクトを含んだQuerySet返します。

特定のデータを取得する

特定のデータを取得するには、条件フィルタを追加して QuerySet を絞り込みます。
QuerySet を絞り込む代表的な方法として次の2つのものがあります。

■filter(**kwargs)
   与えられたパラメータにマッチする新しいQuerySetを返します。
■exclude(**kwargs)
   与えられたパラメータにマッチしない新しい QuerySet を返します。

<重要>
パラメータ (上の関数定義における **kwargs ) の書き方は、フォーマットがあります。
こちらで確認して下さい。

たとえば、2006年以降のブログエントリーの QuerySet を取得するには、 filter() を次のように使用します。(下の2つの式は等価です)

Blog.objects.filter(pub_date__year=2006)
Blog.objects.all().filter(pub_date__year=2006)

4-4. データの削除

データを削除するには、delete()メソッドを使用します。例えば、id=1のブログを削除する場合は次のようにします。

blog = Blog.objects.get(id=1)
blog.delete()

5. Djangoモデル(models.py)のまとめ

  • models.pyを使ってデータベースの構造を定義できる。
  • 各モデルはDjangoのmodels.Modelを継承して作成。
  • モデルにフィールドを追加して、データベーステーブルのカラムを決定。
  • マイグレーションを通じて、データベース構造の変更を反映させる。
  • Django ORMを使用してデータの作成、取得、更新、削除を簡単に行える。

今回はボリュームが多くなってしまいましたが、models.pyはデータベース操作を非常に簡単にする強力なツールです。model.pyを理解しておくことが、開発をスムーズに進める上で肝要です。

ご指摘があれば、是非コメントお願いします。

コメント

タイトルとURLをコピーしました