Views provide the “V” in MVC. Controllers use views to render responses to requests. Ferris provides three different built in views for rendering HTML from templates, JSON from a dictionary, and JSON from an protorpc Message. Alternatively, you can use Response Handlers to generate responses or you may generate responses manually.
In order to provide data to the view, the controller must provide a view context. The context is a simple Python dictionary from which you can pass data from the controller to the view.
Inside of a controller use self.context:
def action(self):
self.context['my_data'] = "Hello!"
These are now available within the view. For example, in the template view:
{{my_data}}
You can pass any Python object into your view via the view context.
The template view is used by default but you can easily switch the view. You can configure it for all actions using Meta.View:
class MyController(Controller):
class Meta:
View = 'json'
Or you can switch dynamically using change_view():
def action(self):
self.meta.change_view('json')
The template view provides glue between controllers and the templating engine. It exposes the view context directly to jinja2. For more details, see Templates.
The JSON view can serialize a dictionary using the standard Python JSON library. For example:
def action(self):
self.meta.change_view('json')
self.context['data'] = {
'hello': 'world'
}
This will return the following when called:
{"hello": "world"}
You must set the data key in the view context for the JSON view to work.
The Messages view will serialize a protorpc Message as JSON. For example:
from ferris import messages
class HelloMessage(messages.Message):
hello = messages.StringField(0)
...
def action(self):
self.meta.change_view('message')
self.context['data'] = HelloMessage(hello="world")
This will return the following when called:
{"hello": "world"}
You must set the data key in the view context for the messages view to work.
Creating a custom view is fairly straightforward. Simply subclass View and implement the render() method:
from ferris.core.views import View
class CustomView(View):
def render(self, *args, **kwargs):
self.controller.events.before_render(controller=self.controller)
self.controller.response.unicode_body = u"Hello, world!"
self.controller.events.after_render(controller=self.controller)
return self.controller.response
Then to use it just use either Meta.View or meta.change_view:
self.meta.change_view('custom')
Views have events similar to controller events, but are handled seperately. These are only used by the template view although you may utilize them for you own custom views as well.
Views events are available form Controllers via self.meta.view.events. These are not preserved when switching views.
View events are available in template views via this.events.
For example, if you wanted to inject scripts into the template using components:
#---- Component:
class ScriptComponent(object):
def __init__(self, controller):
self.controller.meta.view.events.layout_scripts += self.layout_scripts
def layout_scripts(self):
return '<script type="text/javascript" src="/js/myscript.js"></script>'
#---- Controller:
class MyController(Controller):
class Meta:
components = (ScriptComponent,)
#---- Layout:
{{this.events.layout_scripts()}}