Messages

Messages can be used for representing data in a format that’s easily serializable/deserializable. Ferris takes advantage of Google’s protorpc library as well as the helper library protopigeon and provides integration for these libraries into the framework.

The most common use of Messages is to create JSON REST APIs. This use case has its own section.

Message Classes

Protorpc Message classes define the format of data to be transfered across the wire. Here is a sample class:

from ferris import messages

class PostMessage(messages.Message):
    name = messages.StringField(1, required=True)
    content = messages.StringField(2)
    rating = messages.IntegerField(3)

For more information refer to the Google documentation for Message and Message Fields.

Model Messages

Ferris uses protopigeon to automatically generate message classes from models.

ferris.core.messages.model_message(Model, only=None, exclude=None, converters=None)

Creates a protorpc message class for the given model. If only is specified then only the given fields will be used. Similarly, if exclude is given all fields except the ones listed will be used.

Protopigeon can also translate between messages and models:

from ferris import messages

PostMessage = model_message(Post)

msg = messages.to_message(my_post, PostMessage)
ins = messages.to_entity(msg, Post)

For more information see the protopigeon documentation.

Message Responses

You can respond to requests with messages by simply returning the message:

@route
def message(self):
    msg = MyMessage(field1="Hello")
    return msg

The message will automatically be serialized to JSON. This behavior is handled by the message response handler.

You may also use the message view:

@route
def message(self):
    msg = MyMessage(field1="Hello")
    self.meta.change_view('message')
    self.context['data'] = msg

Message Requests

You can use the request parser interface to transform JSON requests into a Message. For example:

@route
def ingest(self):
    parser = self.parse_request(container=MyMessage, parser='Message')
    logging.info(parser.container.field1)

Assuming you POST JSON data such as:

{
    "field1": "Hello!"
}

This would parse the JSON into your message class and log Hello!.

JSON REST APIs

The messaging component provides the ability for controllers to automatically transform models into messages. This can be combined with the scaffold to produce a JSON REST API for your model/controller.

Here’s a full example that exposes a complete RESTful API at /api/posts:

from ferris import Controller, scaffold, messages

class Posts(Controller):
    class Meta:
        prefixes = ('api',)
        components = (scaffold.Scaffolding, messages.Messaging)

    api_list = scaffold.list
    api_view = scaffold.view
    api_add = scaffold.add
    api_edit = scaffold.edit
    api_delete = scaffold.delete
class ferris.core.messages.Messaging

The messaging component handles automatically setting up your controller to process and respond to messages concerning a model.

This works by:

  • Setting the view to the message view.
  • Setting the request parser to the message parser.
  • Transforming ndb Models or Queries in context[‘data’] (or scaffold return values if using scaffolding) to the active message class.

The Messaging component is configured using Controller.Meta.

MessagingMeta.Message

The Message class to use when transforming data. If this is not set then one is automatically generated from Meta.Model using model_message().

MessagingMeta.messaging_prefixes

Configures the prefixes for which the component will be active. By default this is set to the ‘api’ prefix but you may specify a different prefix or more prefixes:

messaging_prefixes = ('remote',)
MessagingMeta.messaging_variable_names

Variables in the view context to check for data when automatically transforming data. By default this is 'data' plus scaffold.singular and scaffold.plural if the scaffolding component is present.

Note that when transforming ndb Queries (such as with scaffold.list) the messages component will use a special list message. The list message is generated by list_message().

ferris.core.messages.list_messsage(Message)

Generates a list wrapper for the given Message. The list wrapper contains the fields:

  • items: A list of Messages for each item in the list.
  • next_page: A link to the next page of results, if applicable.
  • previous_page: A link to previous page of results, if applicable.
  • limit: The maximum number of results, if applicable.
  • count: The length of the list at items.
  • page: The page number, if applicable.

The JSON produced by this message looks like this:

{
    "items": [
        {
            "field1": "Hello!"
        },
        ...
    ],
    "count": 5
}

The next_page, previous_page, page, and limit fields are only present if the messaging component is used in conjunction with the pagination component.