About Blog |

Django template wrapper for Jinja2

So you decided to use Jinja2? But wait, now you want to use django template tags? Well good thing for you, so did I. It’s super easy once you know how to do it. And the cool thing is that it will automatically pick up any tempate tags registered in your install_apps.

Simply embed your extensions within the {% django %} tag extension in jinja, pass in a dictionary (at least a blank one {}) and use your django template tags as normal with one exception: more spaces

"{{"  =  "{ {" 
"{%"  =  "{ %"
"}}"  =  "} }"
"%}"  =  "% }"

Example usage:

<b>hi {{name}}</b>
{% django {"name":"Bob Bobby"} %}
{# filter is a built in django template tag#}
{ % filter force_escape|lower % }
    This text will be <HTML>-escaped,and will appear in all lowercase.

    django name={ {name} } 
    jinja name={{name}}

{ % endfilter % }
{% enddjango %}

output:

<b>hi Timothy John Watts</b>



    this text will be &lt;html&gt;-escaped,and will appear in all lowercase.

    django name=bob bobby 
    jinja name=timothy john watts

code:

from jinja2 import Environment,PackageLoader
from jinja2 import nodes
from jinja2.ext import Extension

class DjangoTagExtension(Extension):
    tags = ['django']

    def __init__(self, environment):
        super(DjangoTagExtension, self).__init__(environment)

    def parse(self, parser):
        lineno = parser.stream.next().lineno

        # get an dict for the django context {}
        args = [parser.parse_expression()]

        body = parser.parse_statements(['name:enddjango'], drop_needle=True)
        return nodes.CallBlock(self.call_method('_tag_support', args),[], [], body).set_lineno(lineno)

    def _tag_support(self, context, *args,**kwargs):
        """Helper callback."""
        from django.template import Context, Template
        raw_template = kwargs['caller']()

        raw_template = raw_template.replace("{ %","{%")
        raw_template = raw_template.replace("% }","%}")
        raw_template = raw_template.replace("{ {","{{")
        raw_template = raw_template.replace("} }","}}")

        django_template = Template(raw_template)

        c = Context(context)

        return django_template.render(c)

and add it to your Jinja Extensions

JINJA_EXTS = (
    'path.to.DjangoTagExtension',
)

order of python @decorators: or how to waste an hour debugging “CSRF cookie not set”

spoiler: @csrf_protect should be the first decorator on a view because it set the cookie with headers.

So we are using Jinja2 on our project. I’ve done some informal benchmarks and Jinja is WAY faster then Django templates.

That is where _all_ advantages end.

{% rant %}

So, this is where all advantages of using Jinja disappear. In a sentence: All built-in and 3rd party template tags do not work in Jinja. Using the django contrib comment tags? Make it again or pass it in from the view. Csrf protection? add it to the context and template yourself.

This gets old.

{% endrant %}

This leads to the topic of this post.

CSRF is implemented with a combination of a token rendered in the template and POSTed to a view and a CSRF cookie that is set on the original view and verified on the view that receives the POST data.

Normally you’d set the CSR middleware and add the token to the form and be done with it. But we had tons of views that would need to be updated so to test is out, only new views were using the comments app would set the csrf_token in the template context and set the @csrf_protect on the views.

Well at some point, it all stopped working with an error “CSRF cookie not set”. And it turned out the @csrf_protect needed to be on the top. Hopefully this can save you time.

Fin.

Coding well: or how not to frustrate the heck out of your future self and others

This is just some things I’ve noticed in the code I’m working on. There are legitimate reasons to do any of the things I’m about to say not to do. However, your reasons are not one of them. Your mileage may vary.

 continue reading

Benchmarking python and django with decorators

in your models.py or views.py

import time                                                

def timeit(method):

    def timed(*args, **kw):
        ts = time.time()
        result = method(*args, **kw)
        te = time.time()

        print '%r (%r, %r) %2.2f sec' % \
          (method.__name__, args, kw, te-ts)
        return result

    return timed

@timeit
def foo():
    pass

then look at your terminal or, instead of printing it write it to a log.

This is saving my code.

from: http://www.zopyx.com/blog/a-python-decorator-for-measuring-the-execution-time-of-methods

First Post

I’ve been too busy doing thing that I should blog, to blog.