Tuesday 22 November 2011

Template inheritance (Jinja2 Python Pyramid)

When creating a website, it's not uncommon to have a base layout for some or all of your pages. In programming, it is a very bad practice to copy that layout for every pages and simply change the content. What happens if you want to modify your base layout? You'd have to perform the same modification to every single pages. In order to solve this, most templating engines support inheritance (or you can mimic it using some other feature). My personal favorite for python is Jinja2. With this templating engine, you can use the following syntax.
{%block NAME%}
content...
{%endblock%}
This defines a "block" with the default content "content...". You can then extend the base file and override the blocks that you want:
{%extends "mytemplate.jinja2"%}
{%block NAME%}
Overridden content
{%endblock}
The content of this template would then be "Overridden content". Now some of you might see the issue here. When using Jinja2 for example, you have to pass a dictionary to the engine so that it can substitutes the variable with the ones in the dictionary. Your page may inherit from your main layout but every variable still needs to be passed from the code. This can become quite messy. This is where the python Decorators can come handy. You first define your main layout function, which will fetch and return all the appropriate data in a dictionary and make a decorator out of it:
def homeLayout(orig):
   def f(request):
      d = orig(req)
      return dict({'menu':getMenu(), 'maincss':static_url('myproj:static/main.css')}), **d)
   return f
This bit of code basically defines a decorator @homeLayout which will take the dictionary returned from the webmethod and add all the variables necessary for the home layout (by merging the two dicts). Now any webmethod decorated with @homeLayout will have the data required for the inherited layout.

No comments:

Post a Comment