お気に入り | 日本語 | ログイン

PolyModel クラス

PolyModel クラスはデータ モデル定義のスーパークラスで、それ自身がその他のデータ モデル定義のスーパークラスになることができます。PolyModel クラスから作成されたクエリには、結果としてクラスまたはそのサブクラスのインスタンスを保持できます。

PolyModel は、google.appengine.ext.db.polymodel モジュールによって提供されます。

PolyModel は Model のサブクラスであり、そのクラスとそのクラスのインスタンス メソッドを継承します。PolyModel クラスは Model のメソッドのいくつかをオーバーライドしますが、新しいインターフェース要素は導入されません。

概要

データ モデルを分類階層として定義できると、非常に便利です。これは、オブジェクト データベースでオブジェクトのあるクラスを別のクラスのサブクラスとして定義することとよく似ています。このようなデータベースは、親クラスのオブジェクトについてクエリを実行し、サブクラスのオブジェクトを結果に含められます。App Engine データストアは本来このような種類のクエリをサポートしませんが、Python SDK に含まれる PolyModel クラスというメカニズムを使用して、この機能を実装できます。

PolyModel から派生したモデル クラスを、他のモデル クラスの基本クラスとすることができます。all()gql() メソッドを使用してこれらのクラスに作成されたクエリは、結果にサブクラスのインスタンスを含むことが知られています。

サブクラスは、親クラスにない新しいプロパティを定義できます。ただし、サブクラスは親クラスのプロパティ定義をオーバーライドできません(オーバーライドすると DuplicateProperty エラーが発生します)。

参考のため、ここのエンティティとモデルからのシンプルな例を示します。PolyModel クラスはパッケージ google.appengine.ext.db.polymodel によって提供されていることに注意してください。

from google.appengine.ext import db
from google.appengine.ext.db import polymodel

class Contact(polymodel.PolyModel):
  phone_number = db.PhoneNumberProperty()
  address = db.PostalAddressProperty()

class Person(Contact):
  first_name = db.StringProperty()
  last_name = db.StringProperty()
  mobile_number = db.PhoneNumberProperty()

class Company(Contact):
  name = db.StringProperty()
  fax_number = db.PhoneNumberProperty()

p = Person(phone_number='1-206-555-9234',
           address='123 First Ave., Seattle, WA, 98101',
           first_name='Alfred',
           last_name='Smith',
           mobile_number='1-206-555-0117')
p.put()

c = Company(phone_number='1-503-555-9123',
            address='P.O. Box 98765, Salem, OR, 97301',
            name='Data Solutions, LLC',
            fax_number='1-503-555-6622')
c.put()

for contact in Contact.all():
  # Returns both p and c.
  # ...

for person in Person.all():
  # Returns only p.
  # ...

PolyModelExpando とは違い、動的プロパティをサポートしません。PolyModel には Expando に相当するものがありません。

ポリモーフィズムはデータストアのネイティブな機能ではありません。その代わり、ポリモーフィズムは PolyModel クラス自体に実装されています。PolyModel サブクラスから作成されたすべてのエンティティは同じ種類のデータストアに保存されます。これはルート クラスの名前です(Animal など)。各オブジェクトはクラス階層を 'class' という名前のエンティティの多値プロパティとして保存します。アプリケーションが PolyModel クラスの all() または gql() メソッドを使用してクエリを作成すると、クエリには 'class' プロパティへのフィルタが適用され、結果はクラスまたは任意のサブクラスから作成されたエンティティに制限されます。

PolyModel はエンティティのプロパティを使用してクラス情報を保存するため、ポリモーフィック クエリのインデックスは 'class' プロパティに対応する必要があります。暗黙的なフィルタは同等フィルタで、その他のプロパティの同等フィルタまたは不等フィルタと組み合わせられます。

注: PolyModel は 'class' プロパティのクラスの名前のみを使用して、フル パスは使用しません。AB および ACB のように、同じ名前の複数のノードでクラス階層を作成することができます。1 つに対するクエリで、両方のエンティティが返されます。同様に、ABC および ACB へのクエリは、機能的に同一です。同じ名前の複数のノードを持つ 1 つのクラス階層を作成しないようにすることが最適です。

コンストラクタ

PolyModel クラスのコンストラクタは、次のように定義されます。

class PolyModel(parent=None, key_name=None, **kw)

別のモデル クラスのスーパークラスになれるモデル クラスで、そのクエリに結果としてサブクラスのインスタンスを含められるクラスです:Model と同様、データ エンティティの種類を定義するには PolyModel クラスのサブクラスを作成する必要があります。

PolyModel は Model のサブクラスであり、そのメソッドを継承またはオーバーライドします。

引数:

parent
新しいエンティティの親であるエンティティの Model インスタンスまたは Key インスタンス。
key_name

新しいエンティティの名前。この名前は主キーの一部になります。None の場合は、システムによって生成された ID がキーとして使用されます。

key_name の値は、先頭を数字にしないでください。また、__*__ という形式にしないでください。ユーザーのアプリケーションは、ユーザーが送信したデータをデータストア エンティティ キー名(メール アドレスなど)として使用するには、たとえば「key:」のような既知の文字列を前に付ける方法で、その値を最初にサニタイズして、上記の要件を満たす必要があります。

key_name は Unicode 文字列として格納され、str 値は ASCII テキストに変換されます。

**kw
インスタンスのプロパティの初期値。キーワードの引数となります。それぞれの名前は新しいインスタンスの属性に対応し、PolyModel クラスで定義された固定属性と対応する必要があります。

クラス メソッド

Model クラスで定義されたクラス メソッドの他、PolyModel クラスは次のクラス メソッドを提供します:

PolyModel.class_key()

クラスの名前と、クラスのすべての親クラスの名前をデータとして返します。

PolyModel.class_name()

クラスの名前を返します。Python クラスの名前が変更された場合は、クラスはこのメソッドをオーバーライドできますが、エンティティは元のクラス名を引き続き使用します。