google.appengine.ext.db.polymodel module

Summary

Support for polymorphic models and queries.

The Model class on its own is only able to support functional polymorphism. It is possible to create a subclass of Model and then subclass that one as many generations as necessary and those classes will share all the same properties and behaviors. The problem is that subclassing Model in this way places each subclass in their own Kind. This means that it is not possible to do polymorphic queries. Building a query on a base class will only return instances of that class from the Datastore, while queries on a subclass will only return those instances.

This module allows applications to specify class hierarchies that support polymorphic queries.

Contents

class google.appengine.ext.db.polymodel.PolyModel(parent=None, key_name=None, _app=None, _from_entity=False, **kwds)source

Bases: google.appengine.ext.db.Model

Base-class for models that supports polymorphic queries.

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

Example

consider the following model hierarchy:

Animal

+——+ +——+ |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 the 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 the 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 the datastore for all sub-casses 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 the 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 GQL query against any sub-hierarchy. For example, to fetch only Canine objects, including all Dogs and Wolves:

db.GqlQuery(“SELECT * FROM Animal WHERE class=’Canine’”)

And alternate method is to use the ‘all’ or ‘gql’ methods of the Canine class:

Canine.all() Canine.gql(‘’)

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.

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’

classmethod all(**kwds)source

Get all instance of a class hierarchy.

Parameters

kwds – Keyword parameters passed on to Model.all.

Returns

Query with filter set to match this class’ discriminator.

classmethod class_key()source

Calculate the class-key for this class.

Returns

Class key for class. By default this is a the list of classes of the hierarchy, starting with the root class and walking its way down to cls.

classmethod class_name()source

Calculate class name for this class.

Returns name to use for each classes element within its class-key. Used to discriminate between different classes within a class hierarchy’s Datastore kind.

The presence of this method allows developers to use a different class name in the datastore from what is used in Python code. This is useful, for example, for renaming classes without having to migrate instances already written to the datastore. For example, to rename a polymorphic class Contact to SimpleContact, you could convert:

# Class key is [‘Information’] class Information(PolyModel): …

# Class key is [‘Information’, ‘Contact’] class Contact(Information): …

to:

# Class key is still [‘Information’, ‘Contact’] class SimpleContact(Information):

… @classmethod def class_name(cls):

return ‘Contact’

# Class key is [‘Information’, ‘Contact’, ‘ExtendedContact’] class ExtendedContact(SimpleContact): …

This would ensure that all objects written previously using the old class name would still be loaded.

Returns

Name of this class.

classmethod from_entity(entity)source

Load from entity to class based on discriminator.

Rather than instantiating a new Model instance based on the kind mapping, this creates an instance of the correct model class based on the entities class-key.

Parameters

entity – Entity loaded directly from datastore.

Raises

KindError when there is no class mapping based on discriminator.

classmethod gql(query_string, *args, **kwds)source

Returns a polymorphic query using GQL query string.

This query is polymorphic in that it has its filters configured in a way to retrieve instances of the model or an instance of a subclass of the model.

Parameters
  • query_string – properly formatted GQL query string with the ‘SELECT * FROM <entity>’ part omitted

  • *args – rest of the positional arguments used to bind numeric references in the query.

  • **kwds – dictionary-based arguments (for named parameters).

classmethod kind()source

Get kind of polymorphic model.

Overridden so that all subclasses of root classes are the same kind as the root.

Returns

Kind of entity to write to datastore.

class google.appengine.ext.db.polymodel.PolymorphicClass(name, bases, dct)source

Bases: google.appengine.ext.db.PropertiedClass

Meta-class for initializing PolymorphicClasses.

This class extends PropertiedClass to add a few static attributes to new polymorphic classes necessary for their correct functioning.