モデルの作成

revision-up-to:11321 (1.1) unfinished

モデルとは、サイトを構成するデータの、唯一絶対的なデータソースを指します。 モデルには、保存したいデータを表すデータフィールドと、データのビヘイビアを 定義します。通常、一つのモデルは一つのデータベーステーブルに対応しています。

モデルの基本として、以下のことを知っておいてください:

  • 各モデルは Python のクラスで、 django.db.models.Model のサブ クラスです。
  • モデルの各アトリビュートの値は、データベース上のあるフィールドを表現 します。
  • モデルの情報をもとに、 Django はデータベース API を自動生成します。 API の詳細は「 クエリを生成する 」で解説します。

参考

このドキュメントを理解する上で、 公式のモデルサンプルリポジトリ が参考になるでしょう。 (Django のソース配布物中では、これらの例は tests/modeltests ディレクトリに入っています。)

簡単な例

以下の例では、 first_name および last_name というフィールドを持った Person モデルを定義しています:

from django.db import models

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

first_namelast_name はモデルの フィールド (fields) です。各 フィールドはクラスのアトリビュートとして定義します。各々のアトリビュートは データベースのカラムに対応します。

上の Person モデルは、以下のようなデータベーステーブルを生成します:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

いくつか、技術的な注意点があります:

  • テーブルの名前 myapp_person はモデルのメタデータから自動的に決定 します。テーブル名は変更できます。「 テーブル名 」を参照して ください。
  • id は自動的に追加されます。この動作も変更できます。 「 主キーフィールドの自動設定 」を参照してください。
  • 上の例の CREATE TABLE SQL 文は PostgreSQL の書式で書かれています が、 Django は 設定ファイル に指定しておいた データベースバックエンドに合わせて適切な SQL を発行します。

モデルを使う

モデルを定義したら、そのモデルを 使う よう Django に指示しましょう。設定 ファイルを編集して、 models.py の入っているパッケージの名前を INSTALLED_APPS 設定に追加してください。

例えば、アプリケーションのモデルが mysite.myapp.models モジュール (mysite.myappmanage.py startapp スクリプトで 作成したアプリケーションのパッケージ) に入っているなら、 INSTALLED_APPS に以下のように書きます:

INSTALLED_APPS = (
    #...
    'mysite.myapp',
    #...
)

新しいアプリケーションを INSTALLED_APPS に追加したら、 manage.py syncdb を忘れずに実行してください。

フィールド

モデルのフィールドは、モデルの定義で最も重要な、かつ最小限必要な要素です。 フィールドは、以下の例のように、クラスのアトリビュートとして定義します:

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

フィールドのタイプ

モデルの各フィールドには、 Field クラスのサブク ラスから、適切なクラスのインスタンスを生成して入れます。Django は、フィール ドのクラスが何であるかという情報を、以下のような判定で使います:

  • データベースのカラム型 (INTEGER, VARCHAR など) の決定
  • Django の管理サイトで使うウィジェット (<input type="text">, <select> など) の決定
  • Django の管理サイトやマニピュレータが実施する最小限のバリデーション の決定

Django にはたくさんのフィールドクラスが組み込みで付属しています。組み込みの フィールドクラス一覧は「 モデルフィールドリファレンス 」にあります。組み込みのフィールドで実現できないことが あれば、フィールドクラスを自分で定義できます。 「 カスタムのモデルフィールド 」を参照してください。

フィールドのオプション

各フィールドクラスには、それぞれフィールド固有の引数がいくつかあります (詳 しくは「 モデルフィールドリファレンス 」を参照し てください)。例えば、 CharField (とそのサブクラ ス) には、データを保存するときの VARCHAR データベースフィールドの長さを 決める必須の引数、 max_length が必要で す。

また、全てのフィールドに共通の引数もあります。共通の引数はどれも省略可能で す。共通の引数は「 リファレンス 」で説 明しています。

ここでは、良く使う引数を簡単に紹介しましょう:

null
True にすると、フィールドの値が空のとき、データベースには NULL を保存します。デフォルトの設定は False です。
blank

True にすると、フィールドの値を空白 (blank) にできます。デフォ ルトの設定は False です。

null とは違うので注意してください。 null は、単に空のデータをデータベース上でどう表現す るかを決めています。一方、 blank はフィールドの値の 検証 (validation) 方法を決めています。あるフィールドに blank=True を指定すると、 Django の管理サイト 上で、そのフィールドを空の値にしたままエントリを作れます。 blank=False にすると、フィールドには必ず値を 入れねばなりません。

choices

iterable (リストまたはタプル) を指定します。 iterable の各要素は フィールドの値の選択肢を表す 2 要素のタプルです。 choices を指定すると、 Django の管理サイト上には、標 準的なテキストフィールドの代わりにセレクタボックスが表示され、ユー ザは選択肢の値だけを選べます。

選択肢のタプル列は、例えば以下のように定義します:

YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
)

各タプルの最初の要素が実際にデータベースに保存される値で、二つめの 要素が管理インタフェースや ModelChoiceField に表示される内容で す。あるモデルオブジェクトのインスタンスで後者の値 (表示値) を取り 出したければ、 get_FOO_display メソッドを使います。例えば、以下 のようなモデルを考えましょう:

from django.db import models

class Person(models.Model):
    GENDER_CHOICES = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
    name = models.CharField(max_length=60)
    gender = models.CharField(max_length=2, choices=GENDER_CHOICES)

gender の表示値は get_gender_display で取り出します:

>>> p = Person(name="Fred Flinstone", gender="M")
>>> p.save()
>>> p.gender
u'M'
>>> p.get_gender_display()
u'Male'
default
フィールドのデフォルト値です。この値は、固定の値でも、関数などの呼 び出し可能オブジェクトでもかまいません。呼び出し可能オブジェクトに した場合、新たなモデルインスタンスを生成するたびにそのオブジェクト を呼び出して、フィールドのデフォルト値を動的に決定します。
help_text
管理サイトでフォームの下に表示される、詳しい「ヘルプ」テキストです。 管理サイトを使っていなくても、定義しておけばドキュメントとして役に 立ちます。
primary_key

True を指定すると、フィールドをモデルの主キーにします。

モデルのどのフィールドにも primary_key=True が指定されていない場合、Django は自動的に IntegerField を追加して主キーを保存します。従って、主キー の設定をデフォルトの状態から変更したいのでないかぎり、 primary_key=True を指定する必要はありま せん。詳しくは「 主キーフィールドの自動設定 」を参照してく ださい。

unique
True の場合、フィールドの値はテーブル全体で一意でなければなりま せん。

前置きしたように、ここではよく使うオプションを簡単に説明するにとどめます。 全オプションの詳しい情報は 「 共通のモデルフィールドオプションのリファ レンス 」を参照してください。

主キーフィールドの自動設定

デフォルトの動作では、 Django は各モデルに以下のフィールド:

id = models.AutoField(primary_key=True)

を追加します。このフィールドは主キーに使われ、フィールドの値はレコードの追 加ごとに自動的にインクリメントされてゆきます。

特定のフィールドを主キーにしたければ、フィールドのオプションに primary_key=True を指定してください。 Field.primary_key の設定されたフィールドの定義があれば、Django は id カラムを自動的に追加しません。

各モデルには必ず一つ primary_key=True のフィー ルドが必要です。

表示用のフィールド名

ForeignKeyManyToManyFieldOneToOneField を除くフィールドクラスは、 第一引数に表示用のフィールド名を指定できます。この引数は省略可能です。引数 を指定しない場合、 Django がフィールドのアトリビュート名のアンダースコアを スペースに置き換えて、表示用のフィールド名を自動的に生成します。

下の例では、表示用のフィールド名は "Person's first name" です:

first_name = models.CharField("Person's first name", max_length=30)

下の例では "first name" です:

first_name = models.CharField(max_length=30)

ForeignKey, ManyToManyField, および OneToOneField クラスでは、第一引数は必須 で、リレーション先のモデルのクラス名を指定せねばなりません。これらのフィー ルドクラスでは、 verbose_name キーワード引数を使って表示用の フィールド名を指定します:

poll = models.ForeignKey(Poll, verbose_name="the related poll")
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(Place, verbose_name="related place")

慣習的に、 verbose_name の先頭の文字は大文字にしません。 Django は必要なときに先頭の文字を自動的に大文字にします。

リレーション

リレーショナルデータベースの威力が、テーブルを相互に関連づけする機能である のはいうまでもありません。Django には、多対一 (many-to-one)、多対多 (many-to-many)、一対一 (one-to-one) といった、よく使うリレーションを定義す る機能があります。

多対一のリレーション

多対一のリレーションを定義するには ForeignKey を使います。このフィールドは他 のフィールド型と同じように、モデルのクラスアトリビュートとして定義できます。

ForeignKey は、リレーションを張る対象のク ラスを指定する必須の引数を一つとります。

例えば、 Car モデルに Manufacturer というフィールドを持たせたいとし ましょう。すなわち、ある Manufacturer には複数の Car が対応するが、 各 Car には一つだけ Manufacturer が対応するようにしたいとしましょう。 この場合、以下のように定義します:

class Manufacturer(models.Model):
    # ...

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer)
    # ...

再帰的リレーション (自分自身に対する多対多 のリレーション) や、 未定義のモデルに対するリレーション も定義できます。「 モデルフィールドのリファレン ス 」を参照してください。

必須ではありませんが、 ForeignKey の名前 (上の例では manufacturer) には、モデル名を小文字にしたものを使うよう勧 めます。もちろん、以下のように、好きな名前を付けてもかまいません:

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(Manufacturer)
    # ...

参考

詳しい例は 多対一のリレーションを持つモデルの例 を参照してください。

ForeignKey フィールドは、リレーションの動作を定 義するための引数をいくつかとれます。各引数は「 モデルフィールドのリファ レンス 」で解説しています。そうした引数を使うと、 リレーションのふるまいを定義する上で役に立ちます。引数は全てオプションです。

多対多のリレーション

多対多の (many-to-many) リレーションを定義するには ManyToManyField を使います。このフィール ドは他のフィールド型と同じように、モデルのクラス属性に含めて使えます。

ManyToManyField には固定引数が一つあり、 リレーションを張る対象のクラスを指定します。

Pizza には複数の Topping オブジェクトを関連付ける例を考えてみましょ う。すなわち、ある Topping は複数のピザの上に置けて、逆にそれぞれのピザ には複数のトッピングを置けるというわけです。このリレーションを表現するには 以下のように定義します:

class Topping(models.Model):
    # ...

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)

ForeignKey と同様、 再帰的リレーション (自分自身に対する多対一のリレーション) や、 未定義のモデルに対するリレーション も定義できま す。「 モデルフィールドのリファレンス 」を参照して ください。

必須ではありませんが、 ManyToManyField の 名前 (上の例では toppings)は、リレーション先のモデル名の複数形にするよ う勧めます。

どちらのモデルで ManyToManyField を定義し てもかまいませんが、どちらか片方のモデルにしか必要ありません -- 両方には指 定できません。

一般的に言って、 Django の管理インタフェースを使うのなら、 ManyToManyField インスタンスを入れておく のは、管理インタフェースで編集される側のオブジェクトにしておくとよいでしょ う。上の例では、 topping は (ToppingManyToManyFieldpizzas をもたせる のではなく) Pizza に入れておきます。というのも、「トッピングを乗せるピ ザ」を編集するよりも「ピザの上に乗せるトッピング」を編集する方が自然だから です。というわけで、上の例のようにすれば、管理サイトの Pizza の編集画面 上でユーザにトッピングを選ばせられます。

参考

詳細な例は 多対多のリレーションを持つモデルの例 を参照してください。

ManyToManyField フィールドは、リレーションの動作 を定義するための引数をいくつかとれます。各引数は「 モデルフィールドの リファレンス 」で解説しています。引数は全てオプショ ンです。

エクストラフィールドで多対多を定義する

Django 1.0 で新たに登場しました: Please, see the release notes

ピザとトッピングを組み合わせたり照合したりするだけのような多対多のリレーショ ンを扱いたいのなら、標準の ManyToManyField で事 足ります。しかし、時として、二つのモデルのリレーションそのものにデータを関 連づけたい場合があります。

例えば、ミュージシャンのグループと、在籍しているミュージシャンを追跡するア プリケーションのケースを考えてみましょう。これは個人 (person) とグループの 関係なので、 ManyToManyField でリレーションを表 現できるはずです。しかし、ミュージシャンとグループの関係には、あるミュージ シャンがあるグループにいつ合流したか、のような細かい情報がたくさんあります。

こうした状況に対応するために、Django には、あらかじめリレーションを管理する ためのモデル (中間モデル) を定義しておき、その中間モデルに向けてエクストラ フィールド (extra field) を組み込んで多対多のリレーションを定義する方法があ ります。中間モデルは ManyToManyFieldthrough 引数に指定します。ミュージシャン の例は以下のように書けます:

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __unicode__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

中間モデルからは、多対多のリレーションの両側にあたるモデルに対して明示的に 外部キーを張らねばなりません。

中間モデルには、いくつか制約があります:

  • 中間モデルは、多対多リレーションのターゲットモデル (リレーションを張 られる側のモデル) に対する外部キーを 一つだけ しか定義できません (上の例では Person ですね)。同じモデルに複数の外部キーを定義する と、モデルのバリデーション時にエラーを送出します。
  • 中間モデルは、多対多リレーションのソースモデル (リレーションを張る側 のモデル) に対する外部キーを 一つだけ しか定義できません (上の例で は Group ですね)。同じモデルに複数の外部キーを定義すると、モデル のバリデーション時にエラーを送出します。
  • 自分自身に対する多対多のリレーションを定義するのに中間モデルを使う場 合にのみ、例外的に同じモデルに対するリレーションを二つ定義できます。 ただし、多対多リレーションの中では、二つの外部キーは別々、すなわちソー スとターゲットを区別して扱います。
  • 中間モデルを使って、あるモデルから自分自身に多対対のリレーションを定 義する場合、 symmetrical=False を指定せねばなりません (「 モデルフィールドのリファレンス 」を参照してください) 。

さて、これで中間モデル (例でいうところの Membership) を使った ManyToManyField を設定したので、多対多のリレーショ ンを生成できます。リレーションの生成は、中間モデルのインスタンス生成によっ て実現します:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason= "Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason= "Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]

通常の ManyToManyField と違って、 addcreate, (beatles.members = [...] のような) 代入では、リレーションの定義は行えま せん:

# 使えません。
>>> beatles.members.add(john)
# これも使えません。
>>> beatles.members.create(name="George Harrison")
# これもまた使えません。
>>> beatles.members = [john, paul, ringo, george]

なぜでしょうか。中間モデルでリレーションを作成するときには、単に PersonGroup の間のリレーションだけではなく、 Membership テーブルのレコー ドを生成するための情報が全て必要だからです。単に addcreate を呼 び出したり代入を行うだけでは、リレーション以外の情報を埋められません。その 結果、中間モデルを使う場合は、 addcreate は使えないのです。 中間モデルを使っている場合、多対多のリレーションを保存するには、中間モデル のインスタンスを生成するしかない、ということを覚えておいてください。

同じ理由で、 remove メソッドも使えません。ただし、 clear() メソッド を使えば、以下のように多対多のリレーションを一括して消去できます:

# ビートルズ解散
>>> beatles.members.clear()

ひとたび中間モデルによる多対多のリレーションを作成したら、通常の多対多リレー ションと同じように、リレーション先のモデルのアトリビュートを使ってリレーショ ンをまたいだクエリを実行できます:

# 'Paul' で始まる名前の人がメンバにいるグループを探す
>>> Groups.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]

中間テーブルを使っているので、中間テーブルのアトリビュートを使ったクエリも 実行できます:

# 1961年1月1日以降に合流した Beatles のメンバを探す
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

一対一のリレーション

一対一のリレーションを定義するには、 OneToOneField を使います。このフィールド も他のフィールド型と同じように、モデルクラスのアトリビュートとして定義しま す。

このリレーションがもっとも有用なのは、あるオブジェクトが別のオブジェクトを 何らかの形で「拡張」している場合の主キーとして使う場合です。

OneToOneField には固定引数が一つあり、リ レーションを張る対象のクラスを指定します。

例えば、「場所 (place)」のデータベースを作るときには、アドレス、電話番号、 といった標準的なものを作成します。その上で、レストランデータベースを作成 するときに、 Restaurant モデルの中に同じフィールドをつくるような 繰り返し作業 (repeat yourself) をする代わりに、場所データベースを基盤にして レストランのデータベースを作成したいとしましょう。このとき、 Restaurant には Place への OneToOneField をもた せられます (レストランは場所に対して "is-a" の関係だからです。実際には、こ のような状況を扱うのに モデルの継承 を使いますが、 モデル継承は OneToOneField で実現されてい ます)。

ForeignKey と同様、 再帰的リレーション未定義のモデルに対するリレーション も定義できま す。詳しくは「 モデルフィールドのリファレンス 」を参 照してください。

参考

詳細な例は 一対一のリレーションを持つモデルの例 を参照してください。

Django 1.0 で新たに登場しました: Please, see the release notes

OneToOneField フィールドは、オプションの引数を一 つとります。引数は「 モデルフィールドリファレンス 」 で解説しています。

以前は、モデル中で OneToOneField を使うと、 そのフィールドは自動的にモデルの主キーになっていました。この仕様はもうなく なりましたが、主キーにしたければ手動で primary_key に指定できます。この 変更により、一つのモデル中で複数の OneToOneField を使えるようになりました。

ファイル間にまたがるモデル

あるモジュールから別のモジュールへのリレーションは全く問題なく張れます。リ レーションを張るには、以下の例のようにモデル定義の先頭でリレーション対称の モデルを import しておき、必要なところでそのモデルクラスを参照します:

from mysite.geography.models import ZipCode

class Restaurant(models.Model):
    # ...
    zip_code = models.ForeignKey(ZipCode)

フィールド名の制約

Django がモデルのフィールド名に課している制約は二つしかありません:

  1. フィールド名は Python の予約語であってはなりません。さもないと Python のシンタクスエラーを引き起こすからです。

    悪い例:

    class Example(models.Model):
        pass = models.IntegerField() # 'pass' は予約語です!
  2. フィールド名には二つ以上の連続するアンダースコアを入れてはなりません。 なぜなら、Django は二重アンダースコアをクエリ照合構文で使っているか らです。

    悪い例:

    class Example(models.Model):
        foo__bar = models.IntegerField() # 二重アンダースコアがあります!
    

データベースのカラム名はフィールドの名前と一致していなくてもよいので、デー タベース側では制約を回避できます。詳しくは後述の db_column を 参照してください。

joinwhere, select のような SQL の予約語を、モデルのフィール ド名に使っても かまいません 。というのも、Django は SQL クエリを生成する ときにデータベーステーブル名やカラム名を常にエスケープするからです。エスケー プにはデータベースエンジン固有のクオート方式を使います。

カスタムのフィールド型

Django 1.0 で新たに登場しました: Please, see the release notes

既存のモデルフィールドが目的とするアプリケーションに合わない場合や、あまり 一般的でないデータベースカラムタイプを活用したい場合のために、独自のフィー ルドクラスを作成できます。カスタムフィールドの詳しい作成方法は 「 カスタムのモデルフィールド 」で説明しています。

Meta オプション

モデルにメタデータを指定するには、以下のようにモデルの内部クラス Meta を使います:

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

モデルのメタデータとは、モデルインスタンスの整列順 (ordering)や、データベース上のテーブル名 (db_table)、モデル名の単数形や複数形 (verbose_name, verbose_name_plural) といっ た、「フィールドの情報でない」情報です。必須のメタデータはなく、 class Meta すら省略できます。

Meta に指定できるオプションの一覧は、「 モデルオプションのリファ レンス 」で解説しています。

モデルのメソッド

カスタムの行レベル ("row-level") の機能をオブジェクトに実装するには、カスタ ムのメソッドを定義します。 Manager メソッドの目 的が「テーブル級 (table-wide)」 の操作であるのに対し、モデルメソッドは個々 のモデルインスタンス単位の操作を実現します。

モデルメソッドは、ビジネスロジックの置き場所をモデル一箇所に限定するための 効果的なテクニックです。

例えば、以下のモデルでは、いくつかカスタムメソッドを定義しています:

from django.contrib.localflavor.us.models import USStateField

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is America-centric...

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
            return "Baby boomer"
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        return "Post-boomer"

    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name)

この例の最後のメソッドは プロパティ (property) です。詳しく は プロパティの説明 を参照してください。

モデルインスタンスのリファレンス 」では、 各モデルに自動的に付与されるメソッド を全て 紹介しています。ほとんどのメソッドはオーバライド可能です。詳しくは後述の 既存のモデルメソッドをオーバライドする を参照してください。といっても、 たいていはせいぜい以下の 2 つのメソッドをオーバライドするぐらいで済むでしょ う:

__unicode__()

オブジェクトの「Unicode 表現」を返す、Python の「マジックメソッド」 です。 Python や Django はこのメソッドを使ってモデルインスタンスに 型強制を適用し、通常の文字列に変換したり表示したりしています。特に、 対話コンソールや管理インタフェース上でオブジェクトを表示するときに 使われています。

このメソッドは常に定義するよう勧めます。定義しておくと、いろいろと 便利だからです。

get_absolute_url()

このメソッドを定義しておくと、 Django にオブジェクトの URL を計算さ せられます。 Django の管理インタフェースなどで、オブジェクトに関連 した URL を特定するときにこのメソッドを使います。

オブジェクトを一意に特定できるような URL を持たせたいときには、この メソッドを定義しましょう。

既存のモデルメソッドをオーバライドする

他にも、データベースの動作をカプセル化していて、カスタマイズ可能な モ デルメソッド があります。特によく変更するのは、 save()delete() の動作でしょう。

こうしたモデルメソッドは、モデルオブジェクトの挙動を変えるために好きなだけ オーバライドできます。

組み込みメソッドをオーバライドする古典的なユースケースに、オブジェクトの保 存時に何か別の処理を行うというものがあります。例を示しましょう (save() のパラメタはドキュメントを参照してください。):

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, force_insert=False, force_update=False):
        do_something()
        super(Blog, self).save(force_insert, force_insert) # 「実際の」 save() を呼び出します。
        do_something_else()

また、以下のようにすれば保存を抑止できます:

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def save(self, force_insert=False, force_update=False):
        if self.name == "Yoko Ono's blog":
            return # Yoko は自分のブログを持っていません!
        else:
            super(Blog, self).save(force_insert, force_update) # Call the "real" save() method.

スーパクラスのメソッド呼び出し、つまり super(Blog, self).save() を忘れ ないでください。この呼び出しを忘れると、デフォルトの処理が行われないため、 データベースにデータが保存されません。

カスタム SQL の実行

もう一つよくあるパターンは、カスタムの SQL 文をモデルメソッドやモジュールレ ベルのメソッドにに書くというものです。詳しくは、 「 素の SQL を扱う 」を参照してください。

モデルの継承

Django 1.0 で新たに登場しました: Please, see the release notes

Django のモデルクラス継承は、 Python の通常のクラス継承とほぼ同じように動作 します。モデル継承を実現するには、一つだけきめておかねばならないことがあり ます。それは、親クラスを (独自のデータベーステーブルを持った) 独立のモデル にしたいか、親クラスを共通情報の単なるホルダとして使い、子クラスでその情報 を扱う形にしたいかです。

Django には 3 種類のモデル継承スタイルがあります。

  1. 複数の子モデルクラスでいちいち同じ情報を入力せずに済ませるために、親モ デルクラスに共通の情報を持たせたいことはよくあります。親モデルクラスを 単体で使うことがないのなら、 抽象ベースクラス を使うのがよ いでしょう。
  2. 一方、(他のアプリケーションなどにある) 既存のモデルをサブクラス化して拡 張したり、個々のモデルに固有のデータベースを持たせたいような場合には、 マルチテーブル継承 を使うのがよいでしょう。
  3. 親モデルクラスのフィールドには手を加えず、 Python レベルでの振る舞いだ けを変えたいのなら、 プロキシモデル を使うのがよいでしょう。

抽象ベースクラス

抽象ベースクラスは、たくさんのモデルに共通する情報を入れておきたいときに便 利な仕組みです。抽象ベースクラスを定義するには、ベースクラス定義の、 Metaabstract=True を入れておきます。モデルを 抽象ベースクラスとして定義すると、そのクラスはデータベーステーブルを生成し ません。その代り、他のモデルを定義するときに抽象ベースクラスを親にすると、 ベースクラスのフィールドが子クラスに追加されます。抽象ベースクラスで定義し たフィールドと同じ名前のフィールドを子クラスで定義しようとするとエラーを引 き起こします (Django は例外を送出します)。

例を示しましょう:

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

このように定義すると、 Student モデルは name, age および home_group の三つのフィールドを持つようになります。. CommonInfo モ デルは抽象ベースクラスなので、通常の Django モデルとしては使えません。 CommonInfo はデータベーステーブルを作らず、マネジャなども持ちません。

ほとんどの用途で使えるのは、このタイプのモデル継承でしょう。抽象ベースクラ スは、子クラスで共通の情報を Python レベルに切り出しながらも、データベース レベルでは、各子クラスに一つのデータベーステーブルを生成します。

Meta の継承

抽象ベースクラスを作成するとき、 Django は抽象ベースクラスの内部クラス Meta をクラス属性として参照できるようにします。子クラ スで Meta クラスを定義しない場合、親クラスの Meta がそのまま継承されます。子クラスで Meta を拡張したければ、親クラスをサブクラス化できます。 以下に例を示しましょう:

class CommonInfo(models.Model):
    ...
    class Meta:
        abstract = True
        ordering = ['name']

class Student(CommonInfo):
    ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'

Django は抽象ベースクラスの Meta クラスを生成するとき に一つだけ手を加えます。すなわち、 Meta の属性を組み 込む前に、 abstract=False を設定するのです。これにより、抽象ベースクラ スの子クラスが自動的に非抽象ベースクラスになります。もちろん、他の抽象ベー スクラスを継承した新たな抽象ベースクラスも定義できます。継承するには、明示 的に abstract=True をセットしてください。

Meta クラスの属性の中には、抽象ベースクラスで定義して も意味のないものもあります。例えば、 db_table を抽象ベースクラスの Meta で定義すると、その子クラス全て (で、独自に Meta を定義しないもの) が、同じデータベーステーブルを 使おうとしてしまいます。

マルチテーブル継承

Django では、継承の各階層にいるクラスが抽象クラスでない実際のモデルであるよ うな、もう一つのタイプのモデル継承をサポートしています。各モデルはそれぞれ が一個のデータベーステーブルを表現していて、個別にクエリを発行したり、イン スタンスを生成したりできます。継承の関係によって、親クラスと子クラスの間に は (自動生成された OneToOneField によって) リンクが張られます。以下の例で説明しましょう:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

Place の全てのフィールドは、 Restaurant からも使えます。しかし、そ れぞれのフィールドのデータは別々のテーブルに格納されます。従って、以下のよ うな操作をどちらも実行できます:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

例えば、 Place であり、かつ Restaurant でもあるようなオブジェクトが あれば、モデル名を小文字にした属性を使って、 Place から Restaurant を取り出せます:

>>> p = Place.objects.filter(name="Bob's Cafe")
# Bob's Cafe が Restaurant オブジェクトなら、子クラスを返す:
>>> p.restaurant
<Restaurant: ...>

ただし、上の pRestaurant クラスで ない のなら (Place から 直接生成されたオブジェクトや、他のクラスの親クラスなら) p.restaurant はエラーを引き起こします。

Meta とマルチテーブル継承

マルチテーブル継承では、子クラスが親クラスの Meta ク ラスを継承する意味がありません。 Meta オプションは全 て親クラスだけに適用されるべきもので、他のクラスに同じ内容を適用しても、矛 盾した振る舞いを引き起こすだけです(これは、独自のテーブルを持たない抽象ベー スクラスと対照的な部分です)。

従って、マルチテーブル継承の子クラスは親クラスの Meta クラスにアクセスする方法を持ちません。ただし、限られたケースで、子クラスが 親クラスの挙動を継承する場合があります。それは、子クラスで django.db.models.Options.ordering または django.db.models.Options.get_latest_by 属性を指定していない場合に、 親クラスの属性を継承するというものです。

親クラスで整列カラムが指定されていて、子クラス側で整列カラムを指定したくな い場合は、明示的設定を無効にしてください:

class ChildModel(ParentModel):
    ...
    class Meta:
        # 親クラスの整列カラム設定の効果を除去する
        ordering = []

継承と逆リレーション

マルチテーブル継承は親クラスと子クラスを暗黙の OneToOneField でリンクするので、前述の例 のように、親クラスから子クラスをたどれます。しかし、子クラスをたどるときに 使う名前は、 ForeignKeyManyToManyField リレーションを定義したと きのデフォルトの related_name と同じ値 を使っています。従って、子クラスで ForeignKeyManyToManyField を別のクラスに向けて張る ときには、 必ず related_name をフィー ルドに指定せねばなりません。指定し忘れると、 Django は manage.py validatesyncdb 時にエラーを 送出します。

例えば、上の Place クラスに対して、 ManyToManyField を持った別のサブクラスを 定義するには、以下のように書きます:

class Supplier(Place):
    # Must specify related_name on all relations.
    customers = models.ManyToManyField(Restaurant, related_name='provider')

親クラスのリンクフィールドを定義する

すでに触れたように、 Django は子クラスと抽象クラスでない親クラスにリンクし た OneToOneField を自動的に生成します。親 クラスへのリンク名を操作したければ、自分で OneToOneField を作成し、パラメタに parent_link=True を渡してください。

プロキシモデル

Django 1.1 で新たに登場しました: Please, see the release notes

When using multi-table inheritance, a new database table is created for each subclass of a model. This is usually the desired behavior, since the subclass needs a place to store any additional data fields that are not present on the base class. Sometimes, however, you only want to change the Python behavior of a model -- perhaps to change the default manager, or add a new method.

This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.

Proxy models are declared like normal models. You tell Django that it's a proxy model by setting the proxy attribute of the Meta class to True.

For example, suppose you want to add a method to the standard User model that will be used in your templates. You can do it like this:

from django.contrib.auth.models import User

class MyUser(User):
    class Meta:
        proxy = True

    def do_something(self):
        ...

The MyUser class operates on the same database table as its parent User class. In particular, any new instances of User will also be accessible through MyUser, and vice-versa:

>>> u = User.objects.create(username="foobar")
>>> MyUser.objects.get(username="foobar")
<MyUser: foobar>

You could also use a proxy model to define a different default ordering on a model. The standard User model has no ordering defined on it (intentionally; sorting is expensive and we don't want to do it all the time when we fetch users). You might want to regularly order by the username attribute when you use the proxy. This is easy:

class OrderedUser(User):
    class Meta:
        ordering = ["username"]
        proxy = True

Now normal User queries will be unorderd and OrderedUser queries will be ordered by username.

Querysets still return the model that was requested

There is no way to have Django return, say, a MyUser object whenever you query for User objects. A queryset for User objects will return those types of objects. The whole point of proxy objects is that code relying on the original User will use those and your own code can use the extensions you included (that no other code is relying on anyway). It is not a way to replace the User (or any other) model everywhere with something of your own creation.

Base class restrictions

A proxy model must inherit from exactly one non-abstract model class. You can't inherit from multiple non-abstract models as the proxy model doesn't provide any connection between the rows in the different database tables. A proxy model can inherit from any number of abstract model classes, providing they do not define any model fields.

Proxy models inherit any Meta options that they don't define from their non-abstract model parent (the model they are proxying for).

Proxy model managers

If you don't specify any model managers on a proxy model, it inherits the managers from its model parents. If you define a manager on the proxy model, it will become the default, although any managers defined on the parent classes will still be available.

Continuing our example from above, you could change the default manager used when you query the User model like this:

class NewManager(models.Manager):
    ...

class MyUser(User):
    objects = NewManager()

    class Meta:
        proxy = True

If you wanted to add a new manager to the Proxy, without replacing the existing default, you can use the techniques described in the custom manager documentation: create a base class containing the new managers and inherit that after the primary base class:

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
    secondary = NewManager()

    class Meta:
        abstract = True

class MyUser(User, ExtraManagers):
    class Meta:
        proxy = True

You probably won't need to do this very often, but, when you do, it's possible.

Differences between proxy inheritance and unmanaged models

Proxy model inheritance might look fairly similar to creating an unmanaged model, using the managed attribute on a model's Meta class. The two alternatives are not quite the same and it's worth considering which one you should use.

One difference is that you can (and, in fact, must unless you want an empty model) specify model fields on models with Meta.managed=False. You could, with careful setting of Meta.db_table create an unmanaged model that shadowed an existing model and add Python methods to it. However, that would be very repetitive and fragile as you need to keep both copies synchronized if you make any changes.

The other difference that is more important for proxy models, is how model managers are handled. Proxy models are intended to behave exactly like the model they are proxying for. So they inherit the parent model's managers, including the default manager. In the normal multi-table model inheritance case, children do not inherit managers from their parents as the custom managers aren't always appropriate when extra fields are involved. The manager documentation has more details about this latter case.

When these two features were implemented, attempts were made to squash them into a single option. It turned out that interactions with inheritance, in general, and managers, in particular, made the API very complicated and potentially difficult to understand and use. It turned out that two options were needed in any case, so the current separation arose.

So, the general rules are:

  1. If you are mirroring an existing model or database table and don't want all the original database table columns, use Meta.managed=False. That option is normally useful for modeling database views and tables not under the control of Django.
  2. If you are wanting to change the Python-only behavior of a model, but keep all the same fields as in the original, use Meta.proxy=True. This sets things up so that the proxy model is an exact copy of the storage structure of the original model when data is saved.

多重継承

Python のサブクラスと同様、 Django のモデルも複数の親モデルクラスを継承でき ます。クラス内の名前解決には、 Python の通常の名前解決規則が適用されるので 注意してください。子クラスで特定の名前 (例えば Meta) を参照する場合、その名前を定義している最初のベースクラスの定義を使い、最初 に名前が見つかった時点で、それ以降同じ名前のオブジェクトの解決は行われませ ん。従って、複数の親クラスで別々に Meta クラスを定義 していても、最初のベースクラスの Meta だけが使われ、 それ以外は全て無視されます。

通常は、モデルの多重継承は必要ないでしょう。多重継承が便利なのは、主に特定 のフィールドやメソッドを追加するための ''mix-in'' クラスを使う場合です。 継承の階層構造はできるだけ単純に、分かりやすくしておきましょう。さもないと、 子クラスで扱っている情報が、どの親クラスから来たか調べるために四苦八苦する はめになるでしょう。

Field name "hiding" is not permitted

In normal Python class inheritance, it is permissible for a child class to override any attribute from the parent class. In Django, this is not permitted for attributes that are Field instances (at least, not at the moment). If a base class has a field called author, you cannot create another model field called author in any class that inherits from that base class.

Overriding fields in a parent model leads to difficulties in areas such as initialising new instances (specifying which field is being intialised in Model.__init__) and serialization. These are features which normal Python class inheritance doesn't have to deal with in quite the same way, so the difference between Django model inheritance and Python class inheritance isn't merely arbitrary.

This restriction only applies to attributes which are Field instances. Normal Python attributes can be overridden if you wish. It also only applies to the name of the attribute as Python sees it: if you are manually specifying the database column name, you can have the same column name appearing in both a child and an ancestor model for multi-table inheritance (they are columns in two different database tables).

Django will raise a FieldError exception if you override any model field in any ancestor model.