NDB Model クラス

Model クラスから継承したクラスは、Datastore に保存されたエンティティの構造を表します。アプリケーションはモデルクラスを定義してエンティティの構造を示し、次にモデルクラスをインスタンス化してエンティティを作成します。モデルクラスはすべて、直接的または間接的に Model から継承します。

このページには、API リファレンス ドキュメントがあります。概要については、NDB エンティティとキーをご覧ください。

はじめに

Model から継承したクラスは、データストアのエンティティを記述します。

モデルクラスはすべて、直接的または間接的に Model から継承します。モデルクラス定義の直接的な割り当てを使用すると、モデルの構造を宣言できます。

from google.appengine.ext import ndb

class Person(ndb.Model):
  name = ndb.StringProperty()
  age = ndb.IntegerProperty()

これで、Person エンティティを作成して、Datastore に書き込めます。

p = Person(name='Arthur Dent', age=42)
k = p.put()

put() からの戻り値は Key で、後で同じエンティティを取得するときに使用できます。

p2 = k.get()
p2 == p  # Returns True

エンティティを更新するには、属性を変更し、もう一度書き込みます(この操作を行っても、キーは変更されません)。

p2.name = 'Arthur Philip Dent'
p2.put()

キーを使用してエンティティを削除することもできます

k.delete()

クラス本体のプロパティ定義は、データストアに保存されたフィールドの名前とタイプをシステムに示します。インデックスに登録されているかどうかは影響しません。また、各デフォルト値なども示されます。さまざまなプロパティ タイプが存在します。

kind は通常、クラス名と同じです(ただし、モジュール名や親スコープは除きます)。kind をオーバーライドするには(スキーマの変更に便利です)、次のように _get_kind() という名前のクラスメソッドを定義します。

  class MyModel(ndb.Model):
    @classmethod
    def _get_kind(cls):
      return 'AnotherKind'

アプリケーションでは、別のモジュールに存在する場合でも、同じ種類のモデルクラスを 2 つ定義することは避ける必要があります。アプリケーションの種類は、グローバルな名前空間とみなされます。

Model サブクラスは、ほとんどのオペレーション(get、put、delete、allocate_ids)でプリコールとポストコールのフックを定義できます。

コンストラクタ

アプリケーションは通常、Model() を呼び出さず、Model から継承したクラスのコンストラクタを呼び出します。これにより、このモデルの新しいインスタンスが作成されます。これはエンティティとも呼ばれます。

新しく作成されたエンティティが自動的にデータストアに書き込まれることはありません。この処理を行うには、put() を明示的に呼び出し、データストアに書き込みを行う必要があります。

引数:

Model サブクラスは、次のキーワード引数をサポートします。

key
このモデルのキー インスタンス。key パラメータを使用する場合、idparentNone(デフォルト)にする必要があります。
id
このモデルのキー ID。id を使用する場合、key は None(デフォルト)にする必要があります。
parent
親モデルのキー インスタンス。最上位モデルの場合は None を指定します。parent を使用する場合、keyNone にする必要があります。
namespace
このエンティティで使用する名前空間。現在の名前空間を使用する場合は None(デフォルト)を指定します。namespace を使用する場合、keyNone にする必要があります。

また、アプリケーションでは、キーワード引数を使用して、モデルのプロパティにマッピングできます。たとえば、次のとおりです:

class Person(ndb.Model):
  name = StringProperty()
  age = IntegerProperty()

p = Person(name='Arthur Dent', age=42)

key、id、parent、namespace という名前のプロパティは簡単に定義できません。たとえば、populate() 呼び出しまたはコンストラクタに key="foo" を渡すと、エンティティのキーは設定されますが、key という名前のプロパティ属性は設定されません。

注: Model サブクラスでコンストラクタをオーバーライドすると、コンストラクタが暗黙的に呼び出される場合があるため、このような呼び出しをサポートする必要があります。Datastore からエンティティを読み取るときに、引数のないコンストラクタを呼び出して空のエンティティが作成されます。その後、キーとプロパティの値が 1 つずつ設定されます。get_or_insert() または get_or_insert_async() が新しいインスタンスを作成すると、コンストラクタに **constructor_args が渡され、キーが設定されます。

クラスメソッド

allocate_ids(size=None, max=None, parent=None, **ctx_options)

このモデルクラスに対してキー ID を割り当てます。

引数

size
割り当てる ID の数。size または max のいずれかを指定できます。両方は使用できません。
max
割り当てる ID の最大数。size または max のいずれかを指定できます。両方は使用できません。
parent
ID を割り当てる親キー。
**ctx_options
コンテキスト オプション

割り当てた範囲の(start、end)を備えたタプルを返します(両端を含みます)。

アプリケーションは、トランザクションで allocate_ids() を呼び出すことはできません。

allocate_ids_async(size=None, max=None, parent=None, **ctx_options)

allocate_ids の非同期バージョン。

結果が(start, end)を備えたタプル(両端を含む)となる Future オブジェクトを返します。

get_by_id(id, parent=None, app=None, namespace=None, **ctx_options)
ID ごとにエンティティを返します。これは Key(cls, id).get() の省略形です。

引数

id
文字列または整数のキー ID。
parent
取得するモデルの親キー。
app(キーワード引数)
アプリケーションの ID。指定しない場合、現在のアプリケーションのデータを取得します。
namespace(キーワード引数)
名前空間。指定しない場合、デフォルト名前空間のデータを取得します。
**ctx_options
コンテキスト オプション

モデル インスタンスを返します。見つからない場合は、None を返します。

get_by_id_async(id, parent=None, app=None, namespace=None, **ctx_options)
get_by_id の非同期バージョン。

結果がモデル インスタンスとなる Future オブジェクトを返します。見つからない場合には None になります。

get_or_insert(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)
トランザクション上で、既存のエンティティを取得します。存在しない場合は、新しいエンティティを作成します。

引数

key_name
取得、作成するキー名(文字列キー ID)。
parent
親エンティティ キー(該当する場合)。
app
アプリケーションの ID。指定しない場合、現在のアプリケーションのデータを取得します。
namespace
名前空間。指定しない場合、デフォルト名前空間のデータを取得します。
context_options
コンテキスト オプション

指定したキー名のインスタンスが存在しない場合、この関数はキーワード引数をモデルクラスのコンストラクタに渡します。指定した key_name のインスタンスと親が存在する場合、これらの引数は破棄されます。

指定したキー名と親を持つ Model クラスの既存のインスタンスを返します。あるいは、作成した新しいインスタンスを返します。

この関数はトランザクションを使用します。この関数を呼び出すコードがトランザクションに存在する場合、既存のトランザクションの再利用を試みます。この関数のエンティティ グループが既存のトランザクションと互換性がない場合、エラーが発生します。

get_or_insert_async(key_name, parent=None, app=None, namespace=None, context_options=None, **constructor_args)

これは、get_or_insert の非同期バージョンです。

指定したキー名と親を持つ Model クラスの既存のインスタンスまたは新しいインスタンスを含む Future オブジェクトを返します。

query([filter1, filter2, ...,] ancestor=None, app=None, namespace=None, filters=None, orders=None, default_options=None, projection=None distinct=False group_by=None)

クエリで説明したように、このクラスに Query オブジェクトを作成します。

キーワード引数 distinct は group_by = projection の省略形です。他のすべてのキーワード引数はクエリ コンストラクタに渡されます。

位置引数を指定すると、初期フィルタの設定に使用されます。

Query オブジェクトを返します。

インスタンス メソッド

populate(**constructor_options)

エンティティ プロパティの値を設定します。キーワード引数は、コンストラクト同じ方法でプロジェクト名を自動的に認識します。

put(**ctx_options)

エンティティのデータをデータストアに書き込みます。エンティティのキーを返します。

引数

**ctx_options
コンテキスト オプション
put_async(**ctx_options)

エンティティのデータをデータストアに非同期的に書き込みます。Future オブジェクトを返します。Future オブジェクトの結果はエンティティのキーです。

引数

**ctx_options
コンテキスト オプション
to_dict(include=all, exclude=None)

モデルのプロパティ値を含む dict を返します。StructuredPropertyLocalStructuredProperty のプロパティ値は再帰的に辞書に変換されます。

引数:

include
含めるプロパティのオプション リスト。デフォルトでは、すべてが対象です。
exclude
除外するプロパティのオプション リスト。includeexclude が重なっている場合には、exclude が優先します。

注: プロパティ値が、変更可能なオブジェクト(反復プロパティを表すリスト、JsonProperty に格納されている辞書やリストなど)の場合、値を明示的に変換する場合(StructuredProperty など)を除き、エンティティに保存されている辞書に同じオブジェクトが返されます。この場合、辞書を変更すると、エンティティが変更されます(その逆も可)。

インスタンス データ

key
Model キーを保存する特別なプロパティ。

フックメソッド

アプリケーションで Model のサブクラスを使用すると、演算前後のフックメソッドとして 1 つ以上のメソッドを定義できます。たとえば、get の前にコードを実行するには、モデル サブクラスの _pre_get_hook() メソッドを定義します。フック関数の記述方法については、モデルフックをご覧ください。

@classmethod
_pre_allocate_ids_hook(cls, size, max, parent)
allocate_ids() の前に実行されるフック
@classmethod
_post_allocate_ids_hook(cls, size, max, parent, future)
allocate_ids() の後で実行されるフック
@classmethod
_pre_delete_hook(cls, key)
delete() の前に実行されるフック
@classmethod
_post_delete_hook(cls, key, future)
delete() の後で実行されるフック
@classmethod
_pre_get_hook(cls, key)
このモデルのエンティティを取得するときに、Key.get() の前に実行されるフック
@classmethod
_post_get_hook(cls, key, future)
このモデルのエンティティを取得するときに、Key.get() の後で実行されるフック
_pre_put_hook(self)
put() の前に実行されるフック
_post_put_hook(self, future)
put() の後で実行されるフック

イントロスペクション

これらのメソッドを使用すると、特定のモデルのプロパティと設定を検査できます。これは、複数のモデルタイプを受け入れるライブラリまたは関数を作成する場合に便利です。

種類による検索

各モデルには種類があります。オーバーライドを行わない限りは通常、種類はクラス名と同じになります。種類と _lookup_model を使用すると、関連するモデルクラスを検索できます。

class Animal(ndb.Model):
    type = ndb.StringProperty()

print Animal._get_kind()  # 'Animal'
print ndb.Model._lookup_model('Animal')  # class Animal

_lookup_model が機能するのは、アプリケーションがインポートしているモデルクラスだけです。

プロパティ

_properties を使用すると、モデルに関連するプロパティのリストを取得できます。

class User(ndb.Model):
    name = ndb.StringProperty()
    email = ndb.StringProperty()

print User._properties
# {'email': StringProperty('email'), 'name': StringProperty('name')}

_propertiesExpando インスタンスにも使用できます。

class Example(ndb.Expando):
  pass

e = Example()
e.foo = 1
e.bar = 'blah'
e.tags = ['exp', 'and', 'oh']
print e._properties
# {'foo': GenericProperty('foo'), 'bar': GenericProperty('bar'),
# 'tags': GenericProperty('tags', repeated=True)}

プロパティのインスタンスにはイントロスペクションを行うことができます。コンストラクタに指定したオプションを参照する場合は、_ で始まるプロパティとして使用します。

print User._properties['email']._name  # 'email'
print User._properties['email']._required  # False
print User._properties['email']._default  # None
print User._properties['email']._choices  # None
print User._properties['email']._compressed  # False
print User._properties['email']._indexed  # True
print User._properties['email']._compressed  # False
print User._properties['email']._repeated  # False
print User._properties['email']._verbose_name  # None
print isinstance(User._properties['email'], ndb.StringProperty)  # True

メソッドのエイリアス

Model クラスのメソッドには、_ で始まるエイリアスがあります。たとえば、_put()put() は同等です。_ で始まるメソッド名を常に使用すると、メソッド名とプロパティ名が競合する可能性があります。ただし、コンストラクタで keyparentid という名前のプロパティは指定できません。

class MyModel(ndb.Model):
    put = ndb.StringProperty()
    query = ndb.StringProperty()
    key = ndb.StringProperty()

entity = MyModel()
entity.put = '1'
entity.query = '2'
entity.key = '3'

entity._put()
print entity
# MyModel(key=Key('MyModel', ...), put=u'1', query=u'2', key=u'3')

print MyModel._query().fetch()
# same as above.

任意のモデルとやり取りを行うサードパーティ ライブラリを作成する場合は、_ で始まるメソッド名の使用をおすすめします。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Python 2 の App Engine スタンダード環境