Models

Models are responsible for persisting data and containing business logic. Models are direct interfaces to Google App Engine’s Datastore. It’s recommended that you encapsulate as much of your business and workflow logic within your models (or a separate service layer) and not your controllers. This enables you to use your models from multiple controllers, task queues, etc without the worry of doing something wrong with your data or repeating yourself. Models can be heavily extended via Behaviors which allow you to encapsulate common model functionality to be re-used across models.

An example model to manage posts might look like this:

from ferris import BasicModel, ndb
from ferris.behaviors import searchable

class Post(BasicModel):
    class Meta:
        behaviors = (searchable.Searchable,)
        search_index = ('global',)

    title = ndb.StringProperty()
    idk = ndb.BlobProperty()
    content = ndb.TextProperty()

Conventions

Models are named with singular nouns (for example: Page, User, Image, Bear, etc.). Breaking convention is okay but scaffolding will not work properly without some help.

Each model class should be in its own file under /app/models and the name of the file should be the underscored class name. For example, to create a model to represent furry bears, name the file /app/models/furry_bear.py. Inside the file, define a class named FurryBear.

App Engine Integration

The Model class is built directly on top of App Engine’s google.appengine.ext.ndb module. You may use any regular ndb.Model class with Ferris. Documentation on propeties, querying, etc. can be found here.

class ferris.core.ndb.Model(*args, **kwds)

Base class that augments ndb Models by adding easier find methods and callbacks.

Ferris provides two simple query shortcuts but it’s unlikely you’ll ever use these directly. Instead, you’ll use the automatic methods described in the next section.

classmethod Model.find_all_by_properties(**kwargs)

Generates an ndb.Query with filters generated from the keyword arguments.

Example:

User.find_all_by_properties(first_name='Jon',role='Admin')

is the same as:

User.query().filter(User.first_name == 'Jon', User.role == 'Admin')
classmethod Model.find_by_properties(**kwargs)

Similar to find_all_by_properties, but returns either None or a single ndb.Model instance.

Example:

User.find_by_properties(first_name='Jon',role='Admin')

Automatic Methods

The Model class automatically generates a find_by_[property] and a find_all_by_[property] classmethod for each property in your model. These are shortcuts to the above methods.

For example:

class Show(Model):
    title = ndb.StringProperty()
    author = ndb.StringProperty()

Show.find_all_by_title("The End of Time")
Show.find_all_by_author("Russell T Davies")

Callbacks

The Model class also provides aliases for the callback methods. You can override these methods in your Model and they will automatically be called after their respective action.

Model.before_put(self)

Called before an item is saved.

Parameters:self – refers to the item that is about to be saved
Note:self.key is invalid if the current item has never been saved
Model.after_put(self, key)

Called after an item has been saved.

Parameters:
  • self – refers to the item that has been saved
  • key – refers to the key that the item was saved as
classmethod Model.before_get(cls, key)

Called before an item is retrieved. Note that this does not occur for queries.

Parameters:key – Is the key of the item that is to be retrieved.
classmethod Model.after_get(cls, key, item)

Called after an item has been retrieved. Note that this does not occur for queries.

Parameters:
  • key – Is the key of the item that was retrieved.
  • item – Is the item itself.
classmethod Model.before_delete(cls, key)

Called before an item is deleted.

Parameters:key – is the key of the item that is about to be deleted. It is okay to get() this key to interogate the properties of the item.
classmethod Model.after_delete(cls, key)

Called after an item is deleted.

Parameters:key – is the key of the item that was deleted. It is not possible to call get() on this key.

These methods are useful for replicating database triggers, enforcing application logic, validation, search indexing, and more.

Access Fields

The BasicModel adds automatic access fields. These are useful for a variety of situations where you need to track who created and updated an entity and when.

class ferris.core.ndb.BasicModel(*args, **kwds)

Adds the common properties created, created_by, modified, and modified_by to Model

ferris.core.ndb.BasicModel.created

Stores the created time of an item as a datetime (UTC)

ferris.core.ndb.BasicModel.modified

Stores the modified time of an item as a datetime (UTC)

ferris.core.ndb.BasicModel.created_by

Stores the user (a google.appengine.api.users.User) who created an item.

ferris.core.ndb.BasicModel.modified_by

Stores the user (a google.appengine.api.users.User) who modified an item.