Notice: Over the next few months, we're reorganizing the App Engine documentation site to make it easier to find content and better align with the rest of Google Cloud products. The same content will be available, but the navigation will now match the rest of the Cloud products. If you have feedback or questions as you navigate the site, click Send Feedback.

Python 2 is no longer supported by the community. We recommend that you migrate Python 2 apps to Python 3.
Stay organized with collections Save and categorize content based on your preferences.

google.appengine.ext.ndb.polymodel module


Polymorphic models and queries.

The standard NDB Model class only supports ‘functional polymorphism’. That is, you can create a subclass of Model, and then subclass that class, as many generations as necessary, and those classes will share all the same properties and behaviors of their base classes. However, subclassing Model in this way gives each subclass its own kind. This means that it is not possible to do ‘polymorphic queries’. Building a query on a base class will only return entities whose kind matches that base class’s kind, and exclude entities that are instances of some subclass of that base class.

The PolyModel class defined here lets you create class hierarchies that support polymorphic queries. Simply subclass PolyModel instead of Model.


class google.appengine.ext.ndb.polymodel.PolyModel(*args, **kwds)source

Bases: google.appengine.ext.ndb.model.Model

Base class for class hierarchies supporting polymorphic queries.

Use this class to build hierarchies that can be queried based on their types.


Consider the following model hierarchy:

  |                 |
+------+          +------+
|Canine|          |Feline|
+------+          +------+
  |                 |
  +-------+         +-------+
  |       |         |       |
+---+   +----+    +---+   +-------+
|Dog|   |Wolf|    |Cat|   |Panther|
+---+   +----+    +---+   +-------+

This class hierarchy has three levels. The first is the ‘root class’. All models in a single class hierarchy must inherit from this root. All models in the hierarchy are stored as the same kind as the root class. For example, Panther entities when stored to Cloud Datastore are of the kind ‘Animal’. Querying against the Animal kind will retrieve Cats, Dogs and Canines, for example, that match your query. Different classes stored in the root class’ kind are identified by their class key. When loaded from Cloud Datastore, it is mapped to the appropriate implementation class.

Polymorphic properties:

Properties that are defined in a given base class within a hierarchy are stored in Cloud Datastore for all subclasses only. So, if the Feline class had a property called ‘whiskers’, the Cat and Panther enties would also have whiskers, but not Animal, Canine, Dog or Wolf.

Polymorphic queries:

When written to Cloud Datastore, all polymorphic objects automatically have a property called ‘class’ that you can query against. Using this property it is possible to easily write a query against any sub-hierarchy. For example, to fetch only Canine objects, including all Dogs and Wolves:


The ‘class’ property is not meant to be used by your code other than for queries. Since it is supposed to represents the real Python class it is intended to be hidden from view. (Although if you feel the need, it is accessible as the ‘class_’ attribute.)

Root class:

The root class is the class from which all other classes of the hierarchy inherits from. Each hierarchy has a single root class. A class is a root class if it is an immediate child of PolyModel. The subclasses of the root class are all the same kind as the root class. In other words:

Animal.kind() == Feline.kind() == Panther.kind() == 'Animal'

Property to store the ‘class key’ of a polymorphic class.

The class key is a list of strings describing a polymorphic entity’s place within its class hierarchy. This property is automatically calculated. For example:

class Foo(PolyModel): ...
class Bar(Foo): ...
class Baz(Bar): ...

Foo().class_ == ['Foo']
Bar().class_ == ['Foo', 'Bar']
Baz().class_ == ['Foo', 'Bar', 'Baz']