Events¶
Ferris has a very simple global pubsub-style event system. Beyond the events emitted by Controllers and Views there’s also a way to globally emit and respond to events.
listeners.py¶
app/listeners.py is used to register global event listeners using on:
For example, to switch from the default theme:
@on('controller_before_startup')
def before_startup(controller, *args, **kwargs):
controller.meta.view.theme = 'corny'
All controller events are prefixed with controller_ when broadcast globally.
Emitting Events¶
You can emit events on the global bus by using fire:
- ferris.core.events.fire(event_name, *args, **kwargs)[source]¶
Calls all of the registered event handlers for a given event. Passes through all arguments
For example:
@route
def transmat(self, item):
fire("item_transmat", item)
Examples¶
There are some very useful cases for using the global event bus.
Setting theme globally¶
As shown above this sets the theme for every controller:
@on('controller_before_startup')
def before_startup(controller, *args, **kwargs):
controller.meta.view.theme = 'corny'
Injecting components¶
If you’d like every controller to contain a particular component:
@on('controller_before_build_components')
def inject_components(controller, *args, **kwargs):
if not MyComponent in controller.Meta.components:
controller.Meta.components += (MyComponent,)
Injecting authorization chains¶
If you’d like every controller to have a particular authorization chain:
@on('controller_before_authorization')
def inject_chains(controller, authorizations):
if not my_chain in authorizations:
authorizations.append(my_chain)
For example, if you’d like to lock down your application to a particular Google Apps domains:
def domain_chain(controller):
user = controller.user
if not user:
return False, "You must be logged"
email_domain = user.email().split('@')[1]
if not email_domain in ('sherpademo.com', 'google.com'):
return False, "Your domain does not have access"
return True
@on('controller_before_authorization')
def inject_authorization_chains(controller, authorizations):
authorizations.insert(0, domain_chain)
Exposing template data¶
If you’d like every template to have access to some particular data:
@on('controller_before_render')
def before_render(controller):
controller.context['custom_data'] = something.get_data()