<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Daniel Banck &#187; jinja2</title>
	<atom:link href="http://dbanck.de/tag/jinja2/feed/" rel="self" type="application/rss+xml" />
	<link>http://dbanck.de</link>
	<description>Webentwicklung - Webdevelopment</description>
	<lastBuildDate>Sat, 09 Jan 2010 00:19:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using Jinja2 with Django</title>
		<link>http://dbanck.de/2009/01/13/using-jinja2-with-django/</link>
		<comments>http://dbanck.de/2009/01/13/using-jinja2-with-django/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 13:55:47 +0000</pubDate>
		<dc:creator>Daniel Banck</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[jinja2]]></category>
		<category><![CDATA[templates]]></category>

		<guid isPermaLink="false">http://dbanck.de/?p=31</guid>
		<description><![CDATA[In the last days I tried to get Jinja2 working with Django.
Here I want to explain a bit about the integration progress.
First we need to install django and jinja2, but I won’t explain it in here, just use easy_install.
After installing you can check if everything works by importing django and jinja2 inside a python shell.
If [...]]]></description>
			<content:encoded><![CDATA[<p>In the last days I tried to get <a href="http://jinja.pocoo.org/2/">Jinja2</a> working with <a href="http://www.djangoproject.com/">Django</a>.<br />
Here I want to explain a bit about the integration progress.</p>
<p>First we need to install django and jinja2, but I won’t explain it in here, just use easy_install.<br />
After installing you can check if everything works by importing django and jinja2 inside a python shell.</p>
<p>If it works we need to create a django project and a example application. (Go for the <a href="http://docs.djangoproject.com/en/dev/intro/tutorial01/#intro-tutorial01">django tutorial</a> if you don’t know how to do this).</p>
<p>Now we need to tell django to use jinja2 to render templates.<br />
The best way to do this is creating a little lib with function to do this which one can import into the views.<br />
So we create inside our project root a directory called libs and there an empty __init__.py file and a file for the jinja2 things.<br />
Lets call it jin.py.</p>
<p>Inside this file we want to create a render_to_response function for jinja2 templates which can be imported from any view.<br />
So here we go:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">http</span> <span style="color: #ff7700;font-weight:bold;">import</span> HttpResponse
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> translation
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">urlresolvers</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_callable
<span style="color: #ff7700;font-weight:bold;">from</span> jinja2 <span style="color: #ff7700;font-weight:bold;">import</span> FileSystemLoader, Environment, PackageLoader, ChoiceLoader
<span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> wraps
&nbsp;
loader_array = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> pth <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'TEMPLATE_DIRS'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    loader_array.<span style="color: black;">append</span><span style="color: black;">&#40;</span>FileSystemLoader<span style="color: black;">&#40;</span>pth<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> app <span style="color: #ff7700;font-weight:bold;">in</span> settings.<span style="color: black;">INSTALLED_APPS</span>:
    loader_array.<span style="color: black;">append</span><span style="color: black;">&#40;</span>PackageLoader<span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
default_mimetype = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'DEFAULT_CONTENT_TYPE'</span><span style="color: black;">&#41;</span>
global_exts = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'JINJA_EXTS'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
env = Environment<span style="color: black;">&#40;</span>extensions=global_exts, loader=ChoiceLoader<span style="color: black;">&#40;</span>loader_array<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>This creates the basic jinja2 environment. Notice that it automatically reads the TEMPLATE_DIRS from settings.py and furthermore you can declare inside the settings file which jinja2 extensions should be loaded.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'jinja2.ext.i18n'</span> <span style="color: #ff7700;font-weight:bold;">in</span> global_exts:
    env.<span style="color: black;">install_gettext_translations</span><span style="color: black;">&#40;</span>translation<span style="color: black;">&#41;</span>
&nbsp;
global_imports = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'JINJA_GLOBALS'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">imp</span> <span style="color: #ff7700;font-weight:bold;">in</span> global_imports:
    method = get_callable<span style="color: black;">&#40;</span><span style="color: #dc143c;">imp</span><span style="color: black;">&#41;</span>
    method_name = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>method,<span style="color: #483d8b;">'jinja_name'</span>,<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> method_name == <span style="color: #008000;">None</span>:
        env.<span style="color: #008000;">globals</span><span style="color: black;">&#91;</span>method_name<span style="color: black;">&#93;</span> = method
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        env.<span style="color: #008000;">globals</span><span style="color: black;">&#91;</span>method.__name__<span style="color: black;">&#93;</span> = method
&nbsp;
global_filters = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'JINJA_FILTERS'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">imp</span> <span style="color: #ff7700;font-weight:bold;">in</span> global_filters:
    method = get_callable<span style="color: black;">&#40;</span><span style="color: #dc143c;">imp</span><span style="color: black;">&#41;</span>
    method_name = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>method,<span style="color: #483d8b;">'jinja_name'</span>,<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> method_name == <span style="color: #008000;">None</span>:
        env.<span style="color: black;">filters</span><span style="color: black;">&#91;</span>method_name<span style="color: black;">&#93;</span> = method
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        env.<span style="color: black;">filters</span><span style="color: black;">&#91;</span>method.__name__<span style="color: black;">&#93;</span> = method
&nbsp;
global_tests = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'JINJA_TESTS'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">imp</span> <span style="color: #ff7700;font-weight:bold;">in</span> global_tests:
    method = get_callable<span style="color: black;">&#40;</span><span style="color: #dc143c;">imp</span><span style="color: black;">&#41;</span>
    method_name = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>method,<span style="color: #483d8b;">'jinja_name'</span>,<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> method_name == <span style="color: #008000;">None</span>:
        env.<span style="color: black;">tests</span><span style="color: black;">&#91;</span>method_name<span style="color: black;">&#93;</span> = method
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        env.<span style="color: black;">tests</span><span style="color: black;">&#91;</span>method.__name__<span style="color: black;">&#93;</span> = method</pre></div></div>

<p>We can also declare the jinja2 globas, filters and tests inside the settings.py via adding:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">JINJA_EXTS = <span style="color: black;">&#40;</span>
    <span style="color: #483d8b;">'jinja2.ext.i18n'</span>,
<span style="color: black;">&#41;</span>
&nbsp;
JINJA_GLOBALS = <span style="color: black;">&#40;</span>
<span style="color: black;">&#41;</span>
&nbsp;
JINJA_FILTERS = <span style="color: black;">&#40;</span>
<span style="color: black;">&#41;</span>
&nbsp;
JINJA_TESTS = <span style="color: black;">&#40;</span>
<span style="color: black;">&#41;</span></pre></div></div>

<p>to it.</p>
<p>So until now our jinja2 environment contains the i18n extension and all other things added in settings.py.<br />
Time to create a render_to_response function.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> render_to_string<span style="color: black;">&#40;</span>filename, context=<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>:
    template = env.<span style="color: black;">get_template</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
    rendered = template.<span style="color: black;">render</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">**</span>context<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> rendered
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> render_to_response<span style="color: black;">&#40;</span>filename, context=<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, request=<span style="color: #008000;">None</span>, mimetype=default_mimetype<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> request:
        context<span style="color: black;">&#91;</span><span style="color: #483d8b;">'request'</span><span style="color: black;">&#93;</span> = request
        context<span style="color: black;">&#91;</span><span style="color: #483d8b;">'user'</span><span style="color: black;">&#93;</span> = request.<span style="color: #dc143c;">user</span>
    rendered = render_to_string<span style="color: black;">&#40;</span>filename, context<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span>rendered,mimetype=mimetype<span style="color: black;">&#41;</span></pre></div></div>

<p>This function also adds the user object to the context if a request is available.</p>
<p>Inside a view we can to render a template with jinja2:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> libs.<span style="color: black;">jin</span> <span style="color: #ff7700;font-weight:bold;">import</span> render_to_response
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'app_name/index.html'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Wow. This wasn’t hard, was it?</p>
<p>But you might notice that the user object still isn’t available.<br />
To get the user object back we would need to pass the request object every time to the render_to_response function. That’s really annoying and looks ugly:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'app_name/index.html'</span>,<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>,request<span style="color: black;">&#41;</span></pre></div></div>

<p>So we create a decorator with some more nice features inside our jin.py:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> jin_renderer<span style="color: black;">&#40;</span>prefix=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> renderer<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
        @wraps<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">global</span> default_mimetype
            response = func<span style="color: black;">&#40;</span>request, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>response, HttpResponse<span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">return</span> response
            <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>response, <span style="color: #008000;">basestring</span><span style="color: black;">&#41;</span>:
                template_name = response
                context_processors = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
                mimetype = default_mimetype
            <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>response, <span style="color: black;">&#40;</span><span style="color: #008000;">tuple</span>, <span style="color: #008000;">list</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
                len_tuple = <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>response<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> len_tuple == <span style="color: #ff4500;">2</span>:
                    template_name, context_processors = response
                    mimetype = default_mimetype
                <span style="color: #ff7700;font-weight:bold;">elif</span> len_tuple == <span style="color: #ff4500;">3</span>:
                    template_name, context_processors, mimetype = response
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> prefix:
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>template_name, <span style="color: black;">&#40;</span><span style="color: #008000;">list</span>, <span style="color: #008000;">tuple</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
                    template_name = <span style="color: #008000;">map</span><span style="color: black;">&#40;</span>correct_path, template_name<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">else</span>:
                    template_name = correct_path<span style="color: black;">&#40;</span>template_name<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span>template_name,context_processors,request,mimetype<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> wrapper
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> correct_path<span style="color: black;">&#40;</span>template_name<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> template_name.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> template_name<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>prefix, template_name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> renderer</pre></div></div>

<p>When using this renderer the request object is always available and we can also define a template prefix path.<br />
Using this new renderer is very easy, too:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> libs.<span style="color: black;">jin</span> <span style="color: #ff7700;font-weight:bold;">import</span> jin_renderer
&nbsp;
render_to_html = jin_renderer<span style="color: black;">&#40;</span><span style="color: #483d8b;">'app_name/'</span><span style="color: black;">&#41;</span>
&nbsp;
@render_to_html
<span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'index.html'</span>,<span style="color: black;">&#123;</span><span style="color: #483d8b;">'test'</span>:<span style="color: #483d8b;">'some context test'</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Now the index.html side your templates/app_name/ will be rendered.</p>
<p>These sites helped me creating the code:<br />
<a href="http://jinja.pocoo.org/2/documentation/">http://jinja.pocoo.org/2/documentation/</a><br />
<a href="http://www.djangosnippets.org/snippets/1112/">http://www.djangosnippets.org/snippets/1112/</a><br />
<a href="http://www.djangosnippets.org/snippets/1061/">http://www.djangosnippets.org/snippets/1061/</a><br />
<a href="http://tinyurl.com/57mojt">http://tinyurl.com/57mojt</a></p>
]]></content:encoded>
			<wfw:commentRss>http://dbanck.de/2009/01/13/using-jinja2-with-django/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
