モデルインスタンスリファレンス

revision-up-to:13211 (1.1) unfinished

このドキュメントでは、モデル API の詳細を解説します。このドキュメントは、 モデルデータベースクエリ <topics-db-queries> といったガイドを前提にしているので、このドキュメントを 読む前に、予め読んで理解しておくとよいでしょう。

このリファレンスでは、 データベースクエリガイドWeblog のモデル例 を使います。

オブジェクトの生成

モデルの新たなインスタンスは、通常の Python のクラスと同じ方法で生成します:

class Model(**kwargs)

キーワード引数に指定できる名前は、モデルで定義したフィールドの名前です。 モデルのインスタンスを生成しても、 save() を呼び出すまでデータベースは 操作されません。

オブジェクトの保存

オブジェクトをデータベースに書き戻すには、 save() を使います:

Model.save([force_insert=False, force_update=False])

もちろん、 データベースへの保存には、以下に説明するような細かい注意点があり ます。

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

save() メソッドのシグネチャが変更されました (force_insertforce_update が追加されました) メソッドをオーバライドするときには、正し いシグネチャを使ってください。

主キーの自動インクリメント

モデルに AutoField 、すなわち自動インクリメントされる主キーがある場合に は、オブジェクトに対して最初に save() を呼び出したときに自動インクリメ ント値が計算され、保存されます:

>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id     # b には ID がないので None を返します。
>>> b2.save()
>>> b2.id     # 新たに保存されたオブジェクトの ID を返します。

ID の値は Django ではなくデータベースによって計算されるので、 save() を 呼び出すまでは ID の値は分かりません。

(利便性のため、明示的に primary_key=True を指定したフィールドを作成しな いかぎり、デフォルトでは各モデルに id という名前の AutoField が追加されます。詳しくは AutoField のドキュメントを参照してください。)

pk プロパティ

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

主キーを自前で定義しているか、 Django によって供給されているかに関係なく、 それぞれのモデルは pk と呼ばれるプロパティを持ちます。 これはモデルの通 常の属性のように振る舞いますが、実はモデルの主キーフィールドのエイリアスで す。その他の属性と同じように、この値は読み書き可能で、モデルのフィールドを 修正し更新できます。

自動主キーの値を明示的に指定する

モデルが AutoField を持っていて、新たなオブジェクトの ID を保存時に明示 的に指定したい場合、 ID を自動的に決定させずに保存前に明示的に指定してくだ さい:

>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id     # Returns 3.
>>> b3.save()
>>> b3.id     # Returns 3.

自動主キーの値を手動で割り当てる場合、決して既に存在する主キーの値を割り当 てないようにしてください! 明示的な主キー値を持った新たなオブジェクトを作成 し、その主キーがすでにデータベース上に存在する場合、 Django は保存操作を新 たなオブジェクトの作成ではなく、既存のオブジェクトの変更とみなします。

上の 'Cheddar Talk' ブログを例にとると、以下の例はデータベース上の既存 のレコードをオーバライドしてしまいます:

b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save()  # Overrides the previous blog with ID=3!

この理由については後述の UPDATE と INSERT の区別 を参照してください。

主キーの衝突がないとはっきり判っている場合なら、自動主キーの値の明示的な指 定は大量のオブジェクトを保存する際にきわめて便利です。

オブジェクトの保存時に何が起きるのか

Django は以下の段階を踏んでオブジェクトを保存します:

  1. ``pre_save`` シグナルの発行 django.db.models.signals.pre_save シグナル の発行によって、何らかのオブジェクトを保存しようとしていることを通知 します。このシグナルを待ち受けている関数でカスタムの処理を実行できま す。

  2. データの前処理 オブジェクトの各フィールドについて、保存時に自動 的に実行する必要があるデータ修飾処理がないか調べ、あれば実行します。

    ほとんどのフィールドは前処理を 伴いません 。フィールドのデータは そのまま保存されます。前処理が行われるのは、特殊な挙動を示すフィー ルドだけです。例えば、 auto_now=True に設定された DateField の場合、前処理の段階で、フィールドの内容が現在の日付になるようデータ を置き換えます (現時点では、「特殊な」挙動を示すフィールドのリストを 全て列挙したドキュメントはありません)。

  3. データベース保存用のデータ準備処理 各フィールドについて、フィー ルドの現在の値を元にデータベースに保存できる型のデータを生成します。

    ほとんどのフィールドはデータ準備処理を 伴いません 。整数や文字列は Python オブジェクトとして「いつでもデータベースへの書き込みに使える」 形式になっています。ただ、より複雑なデータ型の場合、なにがしかの修飾 が必要なことがあります。

    例えば、 DateField は、データの保存に Python の datetime 型 を使います。データベースは datetime オブジェクトを保存しないので、 データベースに保存するには、フィールドの値を ISO 準拠の日付文字列に 変換せねばなりません。

  4. データベースへの保存 前処理と準備処理を経たデータが SQL 文に組み 込まれ、データベースに挿入されます。

  5. ``post_save`` シグナルの発行 ` django.db.models.signals.pre_save シグナルと同じく、オブジェ クトが成功理に保存されたことを通知するために django.db.models.signals.post_save シグナルが発行されます。

UPDATE と INSERT の区別

Django データベースオブジェクトがオブジェクトの作成と変更に同じ save() メソッドを使っていることにお気づきかもしれませんね。 Django は INSERTUPDATE SQL 文のどちらを使うべきかの判断を抽象化しています。具体的 に言うと、 save() を呼び出したときに、Django は以下のアルゴリズムに従い ます:

  • オブジェクトの主キー属性の評価値が False でない場合 (None や 空文字列の場合などでない場合) 、 Django は SELECT クエリを使って、 該当する主キーを持つレコードが存在するかどうか調べます。
  • 該当する主キーを持つレコードがデータベース上に存在する場合には UPDATE クエリを使います。
  • オブジェクトの主キー属性が設定 されていない 場合や、主キーが設定さ れているが該当するレコードは存在しない場合、 INSERT を使います。

新たなオブジェクトを保存する際、まだ使われていない値を主キーに指定できる保 証がないかぎり、主キーの値を明示的に指定しないよう注意してください。詳しく は上記の 自動主キーの値を明示的に指定する の節や、後述の INSERT や UPDATE を強制する を参照してください。

INSERT や UPDATE を強制する

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

ごく稀に、 save() メソッドに INSERT だけを実行させ、 UPDATE に フォールバックさせたくない、あるいはその逆、すなわち UPDATE が可能なら 実行するが、新たなレコードの INSERT はさせたくないような場合があります。 そんなときには、 force_insert=Trueforce_update=True パラメタを save() メソッドに渡してください。 INSERTUPDATE は同時に行え ないので、両方のパラメタを同時に渡すとエラーを引き起こします。

このパラメタが必要なケースは本当にごく稀な場合だけです。たいていは、 Django は正しい SQL で保存を行いますし、パラメタをオーバライドすると、追跡の困難な エラーにつながる恐れがあります。特殊な用途でだけ、このパラメタを使ってくだ さい。

Updating attributes based on existing fields

Sometimes you'll need to perform a simple arithmetic task on a field, such as incrementing or decrementing the current value. The obvious way to achieve this is to do something like:

>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()

If the old number_sold value retrieved from the database was 10, then the value of 11 will be written back to the database.

This can be optimized slightly by expressing the update relative to the original field value, rather than as an explicit assignment of a new value. Django provides F() expressions as a way of performing this kind of relative update. Using F() expressions, the previous example would be expressed as:

>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()

This approach doesn't use the initial value from the database. Instead, it makes the database do the update based on whatever value is current at the time that the save() is executed.

Once the object has been saved, you must reload the object in order to access the actual value that was applied to the updated field:

>>> product = Products.objects.get(pk=product.pk)
>>> print product.number_sold
42

For more details, see the documentation on F() expressions and their use in update queries.

Deleting objects

Model.delete()

Issues a SQL DELETE for the object. This only deletes the object in the database; the Python instance will still be around, and will still have data in its fields.

For more details, including how to delete objects in bulk, see オブジェクトの削除.

その他のモデルインスタンスメソッド

モデルには、特殊な使われ方をするメソッドがあります:

__str__

Model.__str__()

__str__() は、オブジェクトに対して str() を呼び出した際に返す内容を 定義するための Python の特殊メソッドです。 Django はそこかしこで str(obj) (または unicode(obj) -- 下記参照) を使っています。ほとんど は、 Django の admin サイトでオブジェクトをレンダリングして表示したときの値 として、またオブジェクトを表示するときにテンプレートに挿入される値として使 われています。従って、オブジェクトの __str__ は、人間可読なわかりやすい 文字列を返さねばなりません。必須ではありませんが、強く推奨します (ただし、 そこかしこに __str__ メソッドを突っ込んでしまう前に __unicode__ の 説明を良く読んでくださいね)。

例を示します:

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

    def __str__(self):
        # first_name や last_name は Unicode 文字列なので、
        # django.utils.encoding.smart_str() を使う
        return smart_str('%s %s' % (self.first_name, self.last_name))

__unicode__

Model.__unicode__()

__unicode__() メソッドは、オブジェクトに対して unicode() を呼び出し た際に呼び出されます。Django のデータベースバックエンドはモデルの属性値とし て Unicode 文字列を返すので、通常はモデルの __unicode__() メソッドを定 義するとよいでしょう。前節の例を __unicode__() を使って書き直すと、以下 のように簡単になります:

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

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

モデルに __unicode__() メソッドだけを定義して、 __str__() は定義し ないでおくと、 Django が自動的に __str__() メソッドをモデルに追加します。 この __str__() メソッドは、 __unicode__() を呼び出して、その戻り値 を UTF-8 でエンコードした文字列を返します。開発上はこの仕様に従い、 __unicode__() だけを定義して、文字列オブジェクトへの変換は Django 任せ にするよう勧めます。

get_absolute_url

Model.get_absolute_url()

オブジェクトの URL を演算する方法を Django に教えるには get_absolute_url メソッドを定義してください。例えば:

def get_absolute_url(self):
    return "/people/%i/" % self.id

Django はこのメソッドを admin インタフェースで使います。オブジェクトが get_absolute_url() を定義していた場合、オブジェクトの詳細ページには「サ イト上で表示 (View on site)」というリンクが表示されます。このリンクは、オブ ジェクトの get_absolute_url() に基づいて、オブジェクトを公開しているビュー に直接飛べるようになっています。

また、その他にも、例えば 配信フィードフレームワーク などで、 get_absolute_url() を使うことでユーザの利便性を高めています。

テンプレートでオブジェクトの URL を表示する場合、ハードコードするのでは なく get_absolute_url() を使うようにするとよいでしょう。例えば、以下の テンプレート:

<a href="/people/{{ object.id }}/">{{ object.name }}</a>

は良い例ではなく、以下のようにするとよいでしょう:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

ノート

get_absolute_url() の返す文字列は ASCII 文字だけで構成しなければな りません (RFC 2396 の URI 仕様でそのように要求されています)。また、 必要に応じて URL エンコードせねばなりません。 get_absolute_url() を 使うコードやテンプレートが、 get_absolute_url() の返す文字列を、追 加の処理を施さなくても直接利用できるようにせねばならないのです。 URI に Unicode 文字列を沢山使っているのなら、 django.utils.encoding.iri_to_uri() も使うことになるでしょう。

追加のインスタンスメソッド

save(), delete() に加えて、モデルオブジェクトは以下のいずれか、あるい は全てのメソッドを持つことがあります:

Model.get_FOO_display()

choices セットを持つ全てのフィールドについて、オブジェクトは get_FOO_display() メソッドを持ちます。 FOO はフィールド名です。この メソッドは、「人間可読な」フィールド名を返します。例えば、以下のモデル:

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

では、各 Person インスタンスは get_gender_display() メソッド を持ちます:

>>> p = Person(name='John', gender='M')
>>> p.save()
>>> p.gender
'M'
>>> p.get_gender_display()
'Male'
Model.get_next_by_FOO(**kwargs)
Model.get_previous_by_FOO(**kwargs)

null=True であるような DateField および DateTimeField フィール ドについて、オブジェクトは get_next_by_FOO() および get_previous_by_FOO() メソッドを持ちます。 FOO はフィールド名です。 このメソッドは該当の日付フィールドに応じて前のオブジェクトや次のオブジェク トを返します。適切なオブジェクトがなければ DoesNotExist を送出します。

これらのメソッドはいずれもオプションのキーワード引数をとります。引数は 前述の「 Field lookups 」で解説した形式にします。

同じ日付値を持つオブジェクトがある場合、このメソッドは ID を使ったチェック にフォールバックします。これにより、レコードがスキップしたり重複したりしな いことが保証されています。