Avoiding ambiguous mustaches from Jinja2 that includes jQuery templates
Asked Answered
C

2

29

I'm trying to insert jQuery templates into Jinja2 templates. Alas they both (in the default setup) use the mustaches {{ & }} to indicate expressions and literals, respectively.

I'm inserting my jQuery templates into HTML with script tags, like this:

<script type='text/x-jquery-template'>
    <div>The people are:
         {{ each people }} 
          ${$value}
         {{ /each }}
    </div>
</script>

If the above is in a Jinja template, however, it balks because Jinja tries to interpret each as a literal.

In the circumstances (we've lots of templates already) it isn't practical to change Jinja2's start and end delimiters for variables. Plus it's confusing, decreases interoperability, and requires extra training. It is preferable to avoid this option.

So the two alternative things I've thought of to solve this are:

  1. Jinja2 escaping each '{{' and '}}', which I'm not quite sure how to do best ("{{ "{{" }}`, perhaps, but that's verbose);

  2. More practical - perhaps ideal - would be telling Jinja2 to not parse a block of code, perhaps via a jQuery extension.

I'd be grateful for thoughts and feedback. Thank you for reading.

Constellate answered 25/2, 2011 at 12:27 Comment(1)
I, too, have an ambiguous mustache! Reminds me it's time to shave. :)Buxtehude
T
56

You can use the {% raw %}{% endraw %} construct to ease your escaping woes (straight from the Jinja2 docs).

Example:

<script type='text/x-jquery-template'>
    <div>The people are:
        {% raw %}<!-- Everything in here will be left untouched by Jinja2 -->

        {{ each people }} 
          ${$value}
        {{ /each }}

        {% endraw %}
    </div>
</script>
Trematode answered 28/2, 2011 at 0:31 Comment(2)
While escaping and block escaping are nice, I'm coming to the conclusion that the best way is to make sure the server delimiters are all exclusive to the server and the client delimiters are all exclusive to the client, so there is zero escaping required. It seems this is doable by configuring the server template engine to use your own customized delimiters. This gives one the freedom to pick server and client side templating without having escaping be an issue. Note additionally, one should make sure that BOTH engines do not conflict with JavaScript or other client side coding.Frampton
I don’t know if I’ll need it, but I’d like to have the freedom to use Jinja2 features inside my Handlebars templates. The opposite would be appealing too, though, to be able to use the same language on server and client so I can render a default version on the server and then use the same templates to have the client update it.Crasis
A
3

I have found this via google while experimenting with polymer but did not like the proposed solution, so another alternative: Use filters.

In your python code define a filter:

#Filter to create curly braces
@app.template_filter('curly')
def curly(value):
    #Handle value as string  {{'foo'|curly}}
    if(isinstance(value,str)):
        return_value = value
    #Handle value directly. {{foo|curly}}
    else:
        return_value = value._undefined_name
    return "{{" + return_value + "}}"

Then in your template you can use {{'foo'|curly}} or {{foo|curly}}

PS: If you don't use flask I think you can't use the decorator but have to register the filter explicitly instead: environment.filters['curly'] = curly.

Ablution answered 4/4, 2015 at 20:31 Comment(1)
I've been looking at various solutions to this problem this evening and yours is by far the most elegant, and has the massive benefit of playing well with Jasmine and Karma for Unit Testing. Thankyou!!Voltaire

© 2022 - 2024 — McMap. All rights reserved.