Model
クラスから継承したクラスは、Datastore に保存されたエンティティの構造を表します。アプリケーションはモデルクラスを定義してエンティティの構造を示し、次にモデルクラスをインスタンス化してエンティティを作成します。モデルクラスはすべて、直接的または間接的にモデルから継承します。
このページには、API リファレンス ドキュメントがあります。概要については、NDB エンティティとキーをご覧ください。
はじめに
Model
から継承したクラスは、Datastore のエンティティを記述します。
モデルクラスはすべて、直接的または間接的に 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()
クラス本体のプロパティ定義は、Datastore に保存されたフィールドの名前とタイプ、インデックスを付けるかどうか、デフォルト値などをシステムに示します。プロパティの型には、さまざまなものがあります。
kind は通常、クラス名と同じです(ただし、モジュール名や親スコープは除きます)。kind をオーバーライドする(スキーマの変更に役立ちます)には、次のように _get_kind()
という名前のクラスメソッドを定義します。
class MyModel(ndb.Model): @classmethod def _get_kind(cls): return 'AnotherKind'
アプリケーションでは、別のモジュールに存在する場合でも、同じ種類のモデルクラスを 2 つ定義することは避ける必要があります。アプリケーションの種類は、グローバルな名前空間とみなされます。
Model
サブクラスでは、ほとんどのオペレーション(get、put、delete、allocate_ids)に対してプリコールとポストコールのフックを定義できます。
コンストラクタ
通常、アプリケーションは、Model()
を呼び出さず、Model
から継承したクラスのコンストラクタを呼び出します。これにより、このモデルの新しいインスタンスが作成されます。これはエンティティとも呼ばれます。
新しく作成されたエンティティは、Datastore に自動的には書き込まれません。そうするには、put()
を明示的に呼び出して、Datastore に書き込む必要があります。
引数
Model
サブクラスでは、次のキーワード引数がサポートされます。
- key
- このモデルのキー インスタンス。
key
パラメータを使用する場合、id
とparent
は、None
(デフォルト)にする必要があります。 - id
- このモデルのキー ID。
id
を使用する場合、key は、None
(デフォルト)にする必要があります。 - parent
- 親モデルの key インスタンス。最上位モデルの場合は
None
。parent
を使用する場合、key
はNone
にする必要があります。 - namespace
- このエンティティで使用する名前空間。現在の名前空間を使用する場合は、
None
(デフォルト)。namespace
を使用する場合、key
はNone
にする必要があります。
また、アプリケーションでは、キーワード引数を使用して、モデルのプロパティにマッピングできます。たとえば、次のとおりです:
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
- 親エンティティ キー(存在する場合)。
- アプリ
- アプリの 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
オブジェクトの結果は、エンティティの Key になります。引数
- **ctx_options
- コンテキスト オプション
- to_dict(include=all, exclude=None)
-
モデルのプロパティ値を含む
dict
を返します。StructuredProperty
とLocalStructuredProperty
のプロパティ値は、再帰的に辞書に変換されます。引数
- include
- 含めるプロパティのオプション リスト。デフォルトでは、すべてが対象です。
- exclude
- 除外するプロパティのオプション リスト。include と exclude が重なっている場合は、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')}
_properties
は、Expando インスタンスにも使用できます。
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()
と同じです。これは、常に _
で始まるメソッド名を使用すると、メソッド名とプロパティ名が競合する可能性があることを意味します。しかし、コンストラクタに key
、parent
、id
という名前のプロパティを指定することはできません。
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.
任意のモデルを操作するサードパーティ ライブラリを作成する場合は、_
で始まるメソッド名の使用をおすすめします。