Python 2.7 はサポートが終了しており、2026 年 1 月 31 日に
非推奨になります。非推奨になると、過去に組織のポリシーを使用して以前のランタイムのデプロイを再度有効にしていた場合でも、Python 2.7 アプリケーションをデプロイできなくなります。既存の Python 2.7 アプリケーションは、
非推奨日以降も引き続き実行され、トラフィックを受信します。
サポートされている最新バージョンの Python に移行することをおすすめします。
PolyModel クラス
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
注: 新しいアプリケーションを作成する際は、NDB クライアント ライブラリを使用することを強くおすすめします。NDB クライアント ライブラリには、Memcache API によるエンティティの自動キャッシュをはじめ、このクライアント ライブラリにはないメリットがあります。古い DB クライアント ライブラリを現在使用している場合は、DB から NDB への移行ガイドをお読みください。
PolyModel クラスは、自身が他のデータモデル定義のスーパークラスになることができるデータモデル定義のスーパークラスです。PolyModel クラスから生成されたクエリの結果には、クラスやそのサブクラスのインスタンスを含めることができます。
PolyModel
は google.appengine.ext.db.polymodel
モジュールによって提供されます。
PolyModel は Model のサブクラスであり、Model クラスのクラスメソッドとインスタンス メソッドを継承します。PolyModel クラスは Model クラスのメソッドのいくつかをオーバーライドしますが、新しいインターフェース要素は導入しません。
はじめに
オブジェクト データベースでオブジェクトの 1 つのクラスを別のオブジェクトのサブクラスとして定義できるのと同じように、データモデルを分類階層として定義すると便利なことがよくあります。このようなデータベースでは、親クラスのオブジェクトに対してクエリを実行し、クエリ結果にサブクラスのオブジェクトを含めることができます。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.
# ...
ポリモーフィズムはデータストアのネイティブ機能ではなく、PolyModel
クラス自体に実装されます。PolyModel
サブクラスから作成されたエンティティはすべて、同じ種類でデータストアに保管され、その種類(たとえば、Animal
)がルートクラスの名前になります。各オブジェクトはそのクラス階層を、'class'
というエンティティの多値プロパティとして保管します。アプリで PolyModel
クラスの all()
メソッドまたは gql()
メソッドを使用したクエリを作成すると、そのクエリには 'class'
プロパティに対するフィルタが組み込まれ、このクラスまたはそのサブクラスから作成されたエンティティに結果が絞り込まれます。
PolyModel
ではエンティティのプロパティを使用してクラス情報を格納することから、ポリモーフィック クエリのインデックスは 'class'
プロパティに対応する必要があります。暗黙に組み込まれるフィルタは等式フィルタであるため、別のプロパティに対する他の等式フィルタや不等式フィルタと組み合わせることができます。
注: PolyModel では、'class'
プロパティでクラスのフルパスではなく、クラス名のみを使用します。したがって、同じ名前を持つ複数のノードからなるクラス階層が作成される可能性があります(たとえば、A
→ B
と A
→ C
→ B
)。いずれかのノードに対するクエリは、両方のノードのエンティティを返します。同様に、A
→ B
→ C
に対するクエリと A
→ C
→ B
に対するクエリは、機能的にはまったく変わりません。同じ名前を持つ複数のノードからなる単一のクラス階層は作成しないようにするのが最善です。
PolyModel
では、サブクラスでのプロパティ モデル定義のオーバーライドをサポートしていません。サブクラスがスーパークラスで定義されているプロパティを再定義しようとすると、クラス定義で DuplicatePropertyError
が発生します。
PolyModel
では複数の継承をサポートしているため、スーパークラスを共有する複数のクラスから継承することもできます(「菱形」継承)。1 つのクラスが、同じプロパティに対してそれぞれにプロパティ モデルを定義している 2 つのクラスを継承することはできません(その場合、DuplicatePropertyError
が発生します)。ただし、同じスーパークラスから同じプロパティ モデル定義を継承する 2 つのクラスを継承することはできます。
PolyModel
では、Expando とは異なり、動的プロパティをサポートしていません。PolyModel
に相当する Expando
はありません。
コンストラクタ
PolyModel クラスのコンストラクタは次のように定義されます。
- class PolyModel(parent=None, key_name=None, **kwds)
-
他のモデルクラスのスーパークラスになることができるモデルクラスのクエリでは、結果にサブクラスのインスタンスを含めることができます。Model と同様に、PolyModel クラスはサブクラス化してデータ エンティティの種類を定義する必要があります。
PolyModel は Model クラスのサブクラスであり、Model クラスのメソッドを継承またはオーバーライドします。
引数
- parent
- 新しいエンティティの親エンティティの Model インスタンスまたは Key インスタンス。
- key_name
-
新しいエンティティの名前。この名前は主キーの一部となります。None
の場合、システムが生成した ID がキーとして使用されます。
key_name の値を数字で始めることはできません。また、__*__
の形式にすることもできません。アプリケーションでユーザーが送信したデータ(メールアドレスなど)をデータストアのエンティティ キー名として使用する場合、これらの要件を満たすために、最初にデータの前に既知の文字列(「key:」など)を追加するなどして値をサニタイズする必要があります。
key_name
は、str
の値を ASCII テキストに変換した Unicode 文字列として保存されます。
- **kwds
- キーワード引数として使用するインスタンスのプロパティの初期値。それぞれの名前が新しいインスタンスの属性に対応し、PolyModel クラスで定義された固定プロパティに対応している必要があります。
クラスメソッド
Model クラスで定義されているクラスメソッドに加え、PolyModel クラスには次のクラスメソッドがあります。
- PolyModel.class_key()
-
クラスの名前と、クラスの親クラスすべての名前をタプルとして返します。
- PolyModel.class_name()
-
クラスの名前を返します。Python クラスの名前が変更される場合、クラスでこのメソッドをオーバーライドできますが、エンティティでは引き続き元のクラス名を使用する必要があります。
特に記載のない限り、このページのコンテンツはクリエイティブ・コモンズの表示 4.0 ライセンスにより使用許諾されます。コードサンプルは Apache 2.0 ライセンスにより使用許諾されます。詳しくは、Google Developers サイトのポリシーをご覧ください。Java は Oracle および関連会社の登録商標です。
最終更新日 2025-09-04 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["わかりにくい","hardToUnderstand","thumb-down"],["情報またはサンプルコードが不正確","incorrectInformationOrSampleCode","thumb-down"],["必要な情報 / サンプルがない","missingTheInformationSamplesINeed","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2025-09-04 UTC。"],[[["\u003cp\u003eThe \u003ccode\u003ePolyModel\u003c/code\u003e class allows for the creation of data model hierarchies, enabling queries to include instances of both the base class and its subclasses.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003ePolyModel\u003c/code\u003e classes are stored in the datastore under the root class name, and each entity stores its class hierarchy in a \u003ccode\u003e'class'\u003c/code\u003e property, which is used for query filtering.\u003c/p\u003e\n"],["\u003cp\u003eSubclasses of \u003ccode\u003ePolyModel\u003c/code\u003e can introduce new properties but cannot override properties defined in parent classes, raising a \u003ccode\u003eDuplicatePropertyError\u003c/code\u003e if attempted.\u003c/p\u003e\n"],["\u003cp\u003ePolymorphic queries on \u003ccode\u003ePolyModel\u003c/code\u003e require indexes that include the \u003ccode\u003e'class'\u003c/code\u003e property and they support equality filters and can be combined with other filters.\u003c/p\u003e\n"],["\u003cp\u003e\u003ccode\u003ePolyModel\u003c/code\u003e supports multiple inheritance but not dynamic properties or \u003ccode\u003eExpando\u003c/code\u003e, and it's recommended to avoid multiple nodes with same name in class hierarchies.\u003c/p\u003e\n"]]],[],null,["# The PolyModel Class\n\n**Note:**\nDevelopers building new applications are **strongly encouraged** to use the\n[NDB Client Library](/appengine/docs/legacy/standard/python/ndb), which has several benefits\ncompared to this client library, such as automatic entity caching via the Memcache\nAPI. If you are currently using the older DB Client Library, read the\n[DB to NDB Migration Guide](/appengine/docs/legacy/standard/python/ndb/db_to_ndb)\n\nThe PolyModel class is the superclass for data model definitions that can themselves be superclasses for other data model definitions. A query produced from a PolyModel class can have results that are instances of the class or any of its subclasses.\n\n`PolyModel` is provided by the `google.appengine.ext.db.polymodel` module.\n\nPolyModel is a subclass of [Model](/appengine/docs/legacy/standard/python/datastore/modelclass), and inherits its class and instance methods from that class. The PolyModel class overrides several of Model's methods, but does not introduce any new interface elements.\n\nIntroduction\n------------\n\nIt is often useful to define data models as a classification hierarchy, much like how an object database can define one class of objects as a sub-class of another. Such a database can perform queries on objects of the parent class, and include objects of the sub-class in the results. The App Engine datastore does not support this kind of query natively, but you can implement it using a mechanism included with the Python SDK, the `PolyModel` class.\n\nA model class derived from `PolyModel` can be the base class for other model classes. Queries created for these classes using the `all()` and `gql()` methods know to include instances of subclasses in the results.\n\nSubclasses can define new properties not present on parent classes. However, subclasses cannot override property definitions of parent classes. (Doing so results in a `DuplicateProperty` error.)\n\nFor reference, here is the simple example from [Entities and Models](/appengine/docs/legacy/standard/python/datastore/datamodeling). Notice that the `PolyModel` class is provided by the package `google.appengine.ext.db.polymodel`. \n\n```python\nfrom google.appengine.ext import db\nfrom google.appengine.ext.db import polymodel\n\nclass Contact(polymodel.PolyModel):\n phone_number = db.PhoneNumberProperty()\n address = db.PostalAddressProperty()\n\nclass Person(Contact):\n first_name = db.StringProperty()\n last_name = db.StringProperty()\n mobile_number = db.PhoneNumberProperty()\n\nclass Company(Contact):\n name = db.StringProperty()\n fax_number = db.PhoneNumberProperty()\n\np = Person(phone_number='1-206-555-9234',\n address='123 First Ave., Seattle, WA, 98101',\n first_name='Alfred',\n last_name='Smith',\n mobile_number='1-206-555-0117')\np.put()\n\nc = Company(phone_number='1-503-555-9123',\n address='P.O. Box 98765, Salem, OR, 97301',\n name='Data Solutions, LLC',\n fax_number='1-503-555-6622')\nc.put()\n\nfor contact in Contact.all():\n # Returns both p and c.\n # ...\n\nfor person in Person.all():\n # Returns only p.\n # ...\n```\n\nPolymorphism is not a native feature of the datastore. Instead, polymorphism is implemented in the `PolyModel` class itself. All entities created from `PolyModel` subclasses are stored in the datastore with the same kind, which is the name of the root class (e.g. `Animal`). Each object stores its class hierarchy as a multi-valued property of the entity named `'class'`. When the app creates a query using a `PolyModel` class's `all()` or `gql()` method, the query includes a filter on the `'class'` property that limits the results to entities created from the class or any subclass.\n\nBecause `PolyModel` uses a property of the entity to store class information, indexes for polymorphic queries must accommodate the `'class'` property. The implied filter is an equality filter, and can be combined with other equality filters and inequality filters on other properties.\n\n**Note:** PolyModel uses just the names of the classes in the `'class'` property, not full paths. It's possible to create class hierarchies with multiple nodes of the same name, such as `A` → `B` and `A` → `C` → `B`. A query for one will return entities of both. Similarly, queries for `A` → `B` → `C` and `A` → `C` → `B` are functionally identical. It's best to avoid creating a single class hierarchy with multiple nodes of the same name.\n\n`PolyModel` does not support overriding property model definitions in subclasses. If a subclass tries to redefine a property that is defined on a superclass, the class definition raises a `DuplicatePropertyError`.\n\n`PolyModel` supports multiple inheritance, including inheriting from multiple classes that share a superclass (\"diamond\" inheritance). A class cannot inherit from two classes that each define a property model definition for the same property (this would raise a `DuplicatePropertyError`). However, a class can inherit from two classes that inherit the same property model definition from the same superclass.\n\n`PolyModel` does not support dynamic properties, like [Expando](/appengine/docs/legacy/standard/python/datastore/expandoclass) does. There is not an equivalent of `PolyModel` for `Expando`.\n\nConstructor\n-----------\n\nThe constructor of the PolyModel class is defined as follows:\n\nclass PolyModel(parent=None, key_name=None, \\*\\*kwds)\n\n: A model class that can be a superclass to other model classes, and whose queries can include instances of subclasses as results. Like [Model](/appengine/docs/legacy/standard/python/datastore/modelclass), the PolyModel class must be subclassed to define the kind of the data entities.\n\n PolyModel is a subclass of [Model](/appengine/docs/legacy/standard/python/datastore/modelclass), and inherits or overrides its methods.\n\n Arguments\n\n parent\n : The Model instance or Key instance for the entity that is the new entity's parent.\n\n key_name\n\n : The name for the new entity. The name becomes part of the primary key. If `None`, a system-generated ID is used for the key.\n\n The value for key_name must not start with a number, and must not be of the form `__*__`. If your application uses user-submitted data as datastore entity key names (such as an email address), the application should sanitize the value first, such as by prefixing it with a known string like \"key:\", to meet these requirements.\n\n A `key_name` is stored as a Unicode string, with `str` values converted as ASCII text.\n\n \\*\\*kwds\n : Initial values for the instance's properties, as keyword arguments. Each name corresponds with an attribute of the new instance, and must correspond with fixed properties defined in the PolyModel class.\n\nClass Methods\n-------------\n\nIn addition to the class methods defined by the [Model](/appengine/docs/legacy/standard/python/datastore/modelclass) class, the PolyModel class provides the following class methods:\n\nPolyModel.class_key()\n\n: Returns the name of the class and the names of all parent classes for the class, as a tuple.\n\nPolyModel.class_name()\n\n: Returns the name of the class. A class can override this method if the name of the Python class changes, but entities should continue using the original class name."]]