You need to create a model class for your entity. You can do this in two ways:
- Create a model class that defines entity properties.
- Create an expando model class that does not define entities in advance.
This document describes how to create each of these types of model classes.
It also describes how to create a model hook, so that your
application can run some code before or after some type of operations, for
example, before each get()
.
Creating a model class with properties
Before creating an entity, you must create a model class that defines one or more entity properties. For example:
...
where you want each Account entity to have properties for user name, user ID, and email.
For a full list of property types, see the Entity Property Reference.
Creating an Expando model class
You don't have to use a model class that defines properties in advance.
A special model subclass called Expando
changes the behavior of
its entities so that any attribute assigned is saved to the data store. Note
that such attributes can't start with an underscore.
Here is how to create an Expando model:
...
This writes an entity to the data store with a
foo
property with integer value 1
,
a bar
property with string value 'blah'
,
and a repeated tag
property with string
values 'exp'
, 'and'
, and 'oh'
.
The properties are indexed, and you can inspect them using the
entity's _properties
attribute:
An Expando
created by getting a value from
the data store has properties for all property values that were saved
in the data store.
An application can add predefined properties to an
Expando
subclass:
...
This gives employee
a name
attribute with value 'Sandy'
,
an age
attribute with value None
,
and a dynamic attribute location
with value 'SF'
.
To create an Expando
subclass whose properties are unindexed,
set _default_indexed = False
in the subclass definition:
...
You can also set _default_indexed
on an Expando
entity.
In this case it will affect all properties assigned after it was set.
Another useful technique is querying an Expando
kind for a dynamic property. A
query like the following
won't work, because the class doesn't have a property object for the location
property. Instead, use GenericProperty
, the class Expando
uses for dynamic
properties:
Using Model Hooks
NDB offers a lightweight hooking mechanism. By defining a hook, an application
can run some code before or after some type of operations; for example, a Model
might run some function before every get()
.
A hook function runs when using the synchronous, asynchronous and multi versions
of the appropriate method. For example, a "pre-get" hook would apply to all of
get()
, get_async()
, and get_multi()
. There are pre-RPC and post-RPC versions
of each hook.
Hooks can be useful for the following:
- query caching
- auditing Cloud Datastore activity per-user
- mimicking database triggers
The following example shows how to define hook functions:
...
...
If you use post-hooks with asynchronous APIs, the hooks are triggered by calling
check_result()
, get_result()
or yielding (inside a tasklet) an async
method's future.
Post hooks do not check whether the RPC was successful;
the hook runs regardless of failure.
All post- hooks have a Future
argument at the end of the call signature. This Future
object
holds the result of the action. You can call get_result()
on this Future
to retrieve the result; you can be sure that get_result()
won't block, since the Future
is complete by the time the hook is called.
Raising an exception during a pre-hook prevents the request from taking place.
Although hooks are triggered inside <var>*</var>_async
methods, you cannot
pre-empt an RPC by raising tasklets.Return
in a pre-RPC hook.