Extending Uliweb¶
A web framework might fall short to anticipate all your development needs. Although Uliweb is no exemption in this respect, it strives to provide the most possible amount of flexibility and extensibility.
Dispatch System¶
Uliweb ships with a dispatch module, it's in uliweb/core folder.
Dispatch units¶
Uliweb provides a simple Dispatch system that consists of three units:
- Dispatch point
- Receiver function
- Collection system
Dispatch points¶
An Dispatch point will define the place where the dispatcher want to call its associated receiver functions, and it'll pass the auguments to those receiver functions. A dispatch point will looks like:
dispatch.call(sender, topic, signal=None, *args, **kwargs)
or
ret = dispatch.get(sender, topic, signal=None, *args, **kwargs)
You can see there are two arguments must be passed:
senderIt just looks like the name.topicEach dispatch has an topic, so that only the receiver functions which associated with this topic will be called. So different dispatch point can send the same topic.
And the signal is optional. If this argument is not None, then only the receiver functions which the topic and the signal are all matched will be called. If the value of signal argument is None, then all receiver functions which as soon as the topic is matched will be called.
Except for above three arguments, you can also pass other arguments, and you should ensure the receiver functions must match with them.
When you run a dispatch point(It's just a common function invoding), dispatch system will find all matched receiver functions according the topic and optional signal, and call them one by one, according the order specified in definition of receiver function. Why there are two kinds of invoking functions? Because:
callwill invoke matched receiver functions one by one, and you can't interrupt it inn the middle of the execution, and it won't return a value(or it'll just return None).getwill invoke just likecall, but if one receiver function returns a value is not None, the execution will not continue, and return this value immediately.
So the execution of a dispatch point just like a chain, and you can use different methods to affect its execution.
Receiver functions¶
It's a function will be used for processing special topic and optional signal. The signature of a receiver function will look like:
def receiver(sender, topic, *args, **kwargs)
So, receiver functions are very common.
Collection system¶
Collection system is used to collect all of avaible receiver functions, so that when executing a dispatch point, it can find all associated receiver functions. So there are two things you need to do after defining the receiver functions:
Call dispatch.bind to receiver functions, for example:
from uliweb.core.dispatch import bind @bind('test_point') def receiver(): ...- Put the code to the right place, so that uliweb can import them, and calling the bind function. When Uliweb startup, it'll try to import all
start.pyfrom every available app, so you can put the code to__init__.pyorstart.pyof each app folder.
The signature of the bind function is:
def bind(topic, signal=None, kind=MIDDLE, nice=-1)
topicwhich you want to bind tosignalused to match with the dispatch point signal argument. And if the receiver function has no signal argument, this argument will be removed. On the contrary, it'll be passed to the receiver function.kindThere are two types of indicating the priority of a receiver function. And priority is higher(the number is lower), the execution order is in front. So 0 will highter than 100. And kind has three levels:HIGH, MIDDLE, LOW, and they are mapping to different priority number: HIGH=100, MIDDLE=500, LOW=900. And default is MIDDLE.niceYou should not use kind and nice at the same time. Andniceis used for accurately setting the priority.
When executing a dispatch point, it'll sort all associated receiver functions according their priority. So if your receiver functions need to run in certain order, you'll need to set kind or nice argument.
Predefined dispatch points¶
uliweb.core.SimpleFrame¶
- dispatch.call(application, 'startup_installed')
Dispatcher class initialization, will only run once for class
- dispatch.call(application, 'startup')
Dispatcher has already startuped, will be executed when creating every Dispatcher instance.
- dispatch.call(application, 'prepare_view_env', Dispatcher.env
Used for prepare global view and template execution environment. All objects in env can be used in any view function directly.
