As you may have guessed, Controllers are the ‘C’ in MVC. They are responsible for processing and responding to HTTP requests. Controllers contain methods called Actions that respond to requests, and are typically lightweight classes that glue the Models to the Templates.

Although controllers are typically associated with a single model, it’s completely possible to use multiple or no models at all. Usually you’ll want to put most of your business logic in your models and simply write glue code in the controller. Controllers can be extended with Components and scaffolded.

The routing layer determines which Controller and Action to call when a request is made.

class ferris.core.controller.Controller[source]

Controllers allows grouping of common actions and provides them with automatic routing, reusable components, request data parsering, and view rendering.

A Controller that deals with time travel might look like this:

from ferris import Controller, route

class Tardis(Controller):
    class Meta:
        prefixes = ('admin',)
        components = (Extrapolator, Time)

    def list(self):
        return 'We are currently at %s' % self.components.time.current()

    def set(self, time):
        return "Time set to %s" % self.components.time.current()

    def admin_self_destruct(self):
        return "Run!"

The implementation of the “Extrapolator” and “Time” components is left as an exercise for the reader.


Controllers are named plural nouns in upper camel case (UpperCamelCase) from the models that they are associated with (for example: Pages, Users, Images, Bears, etc.). There are many cases where the plural convention doesn’t make sense, such as controllers that don’t have an associated model or controllers that span multiple models.

Each controller class should be in its own file under /app/controllers and the name of the file should be the underscored class name. For example, to create a controller to act on fuzzy bears, create the file /app/controller/ Inside, define a class named FuzzyBears.

This section focuses on actions and how to process and respond to requests. Other features are tied into controllers in various ways. Actions are exposed via the Routing system. Controllers can automatically render a view, process POST and JSON data and attach it to Forms or Messages using Request Parsers. Finally, controllers also allow you to break out common functionality using Components.


class Controller.Meta[source]

The Meta class stores configuration information for a Controller. This class is constructed into an instance and made available at self.meta. This class is optional, Controllers that do not specify it will receive the default configuration. Additionally, you need not inherit from this class as Controller’s metaclass will ensure it.

For example:

def Posts(Controller):
    class Meta:  # no inheritance
        prefixes = ('admin', )
        #  all other properties inherited from default.
Parser = 'Form'

Which RequestParser class to use by default. See Controller.parse_request().


Which View class to use by default. use change_view() to switch views.

alias of TemplateView

authorizations = (<function inner_inner at 0x2b93f4f8e938>,)

Authorizations control access to the controller. Each authorization is a callable. Authorizations are called in order and all must return True for the request to be processed. If they return False or a tuple like (False, ‘message’), the request will be rejected. You should always have auth.require_admin_for_prefix(prefix=('admin',)) in your authorization chain.

change_view(view, persist_context=True)[source]

Swaps the view, and by default keeps context between the two views.

Parameters:view – View class or name.
components = ()

List of components. When declaring a controller, this must be a list or tuple of classes. When the controller is constructed, controller.components will be populated with instances of these classes.

prefixes = ()

Prefixes are added in from of controller (like admin_list) and will cause routing to produce a url such as ‘/admin/name/list’ and a name such as ‘admin:name:list’

This Meta class is also used to configure components:

class Meta:
    components = (Pagination,)
    pagination_limit = 5

The Meta class is constructed and made available via self.meta (lowercase). You can use this to change configuration on the fly:

def list_long(self):
    self.meta.pagination_limit = 50


Actions are normal instance methods that can be invoked via HTTP. Actions are responsible for receiving requests and generating a response.

Ferris takes care of automatically routing actions and generating URLS. The CRUD actions list, view, add, edit, and delete are automatically routed. Other actions have to be explicitly marked for routing.

A simple action might look like this:

# via /controller/echo/<text>
def echo(self, text):
    return text


Actions can access the current request using self.request:

def list(self):
    return self.request.path

For more information on the request object see the webapp2 documentation on requests.


Actions can also access the GET and POST variables using self.request.params:

# i.e. /controller?text=meow
def list(self):
    return self.request.params['text']

For just GET variables use self.request.GET, and for POST only use self.request.POST. PUT and PATCH data are always in self.request.POST.

More complex request data such as Forms and Messages instance handled using Request Parsers.


Actions can also take various parameters on the URL as described in Routing:

# /controller/concat/<text>/<number>
def concat(self, text, number):
    return text + str(number)

User & Session

Controller.user = None

The current user as determined by google.appengine.api.users.get_current_user().


Sessions are a simple dictionary of data that’s persisted across requests for particular browser session.

Sessions are backed by an encrypted cookie and memcache.

For example:

def user_profile():
    if not 'profile' in self.session:
        self.session['profile'] = UserProfile.find_by_user(self.user)
    return self.session['profile']

Route Info

The controller provides all of the information about the current route via self.route. The purpose of these variables is explained in depth in Routing.


The current action, such as ‘add’, ‘list’, ‘edit’, etc.


The current prefix, such as None, ‘admin’, ‘api’, etc.


The current controller’s name.

The canonical route name, as generated by URL and Name Generation.


Any positional arguments passed inside of the route’s url template.


Any keyword arguments passed inside of the route’s url template.


Ferris simplifies responding by allowing you to return plain types that get transformed into responses or just allowing the Views to auto-render. However, it’s often useful to directly access the response to set headers or output binary data. Actions can directly access the current response using self.response:

def list(self):
    self.response.headers['x-test'] = "greeting"
    return self.response

For more information on the request object see the webapp2 documentation on responses.

Return Values

Ferris uses Response Handlers to transform anything returned from an action into a response.

Actions can return a string and the string will become the body of the response with the content-type ‘text/html’:

def list(self):
    return 'Hi!'

You can set the content-type before hand if you’d like:

def list(self):
    self.response.content_type = 'text/plain'
    return 'plain, plain, old text.'

Actions can return an integer and the will become the status of the response, in this case the response will be a 404 Not Found:

def list(self):
    return 404

Actions can return any webapp2.Response class, including self.response:

def list(self):
    self.response.content_type = 'application/json'
    self.response.text = '[0,1,2]'
    return self.response

Even if you return a string or integer, any changes to self.response are kept (except for the body or status, respectively):

def list(self):
    self.response.content_type = 'text/xml'
    self.response.headers['cache-control'] = 'nocache'
    return '<x>Hello!</x>'

Returning nothing (None) will trigger the automatic view rendering unless self.meta.view.auto_render is set to False. See Views for more information:

def list(self):
    # nothing returned, so by default 'app/templates/controller/list.html' will be rendered.


Redirects can be generated using self.redirect and uri():

def auto(self):
    return self.redirect(self.uri(action='exterminate', who='everything'))


Controllers are secured using Authorization Chains.


class Controller.Util[source]

Provides some basic utility functions. This class is constructed into an instance and made available at controller.util.

static decode_key(str, kind=None)

Decodes a urlsafe ndb.Key.

static encode_key(ins)

Encode an ndb.Key (or ndb.Model instance) into an urlsafe string.

static parse_json(str)

Decodes a json string.

static stringify_json(data)

Encodes a json string.

decode_key is especially useful for working with urlsafe keys:

def one(self):
    item = Widget.find_by_name('screwdriver')
    return self.redirect(
        self.uri(action='two', key=item.key.urlsafe()))

def two(self, key):
    item = self.util.decode_key(key).get()

The Startup Method and Events

Handlers have various Events that are called during the lifecycle of a request. Event handlers should be registered at the beginning of a request using the startup callback method.


Called when a new request is received and before authorization and dispatching. This is the main point in which to listen for events or change dynamic configuration.

You can tap into these events using which is a NamedEvents instance:

def startup(self): += self.on_after_dispatch

def self.on_after_dispatch(self, controller=None, response=None):'hello!')


For a usual request, the events in order are:

  1. setup_template_variables
  2. before_build_components, after_build_components
  3. before_startup, after_startup
  4. before_dispatch, after_dispatch
  5. template_names (only if using TemplateView)
  6. before_render, after_render (only if a view is rendered)
  7. dispatch_complete

These events are broadcast to the global event bus with the prefix controller_.