Bottle's view decorator and default variables
Bottle’s @view decorator provides a simple way to designate a template to render an HTML page. Your view function just has to return a dictionary, and its contents can be accessed from the template using the '{{ name }}' syntax.
The @view decorator can also take keyword arguments. These are treated as default template variables - if the dictionary returned by your view function doesn’t have a key for one of the keyword arguments then the template will use the value passed into the decorator, like so:
from bottle import view
@view('default.html', author='David Buxton')
def home():
return {'title': 'Home page'}
That would render any instance of '{{ author }}' as 'David Buxton'. And then you can have another view function that overrides the keywords by returning a different value in the dictionary:
from bottle import view
@view('default.html', author='David Buxton')
def music():
return {'title': 'Thalassocracy', 'author': 'Frank Black'}
And at that point I wonder what is the advantage of using keyword arguments with @view: you have to decorate each function separately, and if you want to override a keyword in your return dictionary then it would be easier not to specify the keyword in the first place.
Thus the real point of using keywords with the @view function is only apparent if you curry the @view decorator with keywords first so that you can re-use the curried decorator and avoid repeating yourself.
Someday I will re-write the previous sentence. Until then, sorry.
Instead of passing a default author each time as in the examples above, let’s make a new @view decorator (using Python’s functools module) and then use that on each view function:
import functools
from bottle import view
view = functools.partial(view, author='David Buxton')
@view('default.html')
def home():
return {'title': 'Home page'}
@view('default.html')
def music():
return {'title': 'Thalassocracy', 'author': 'Frank Black'}
The new decorator means you get the default keyword arguments wherever you use @view while permitting any function to override those defaults in the dictionary it returns.
And if you wanted to get really lazy you could even pass in a template name when wrapping the decorator with functools.partial, however you would not be able to use your wrapped decorator to change the template name because it is a positional argument (like what it explains here in the functools documentation). You would also have to call the decorator with no arguments like '@defaultview()'. So forget I mentioned it.
I’m not saying you are lazy.