How to protect some files from the Jinja template processor? - python

I am using cookiecutter to create a tornado project, using this template (it has several bugs, so you'll probably won't be able to use it out of the box). I have hit a problem which I do not know how to solve:
jinja2.exceptions.TemplateSyntaxError: unexpected char '\\' at 124272
File "./{{cookiecutter.project_slug}}/static/swagger/lib/jsoneditor.min.js", line 10
I am not sure, but I have the impression that cookiecutter is trying to Jinja-process the jsoneditor.min.js, which is not supposed to happen, since the "templating" in that file is not supposed to be processed by cookiecutter, it just happens to include the same escape characters that Jinja is using.
Is it possible to tell cookiecutter not to process files inside a certain directory? This is probably a matter of properly setting up the cookiecutter template, but not sure how this can be specified.

By default cookiecutter will try to process every file as a jinja template which produces wrong results if you have something that looks like a jinja template but is only supposed to be taken literal. Starting with cookiecutter 1.1 one can tell cookiecutter to only copy some files without interpreting them as jinja template (documentation).
To do that you have to add a _copy_without_render key in the cookiecutter config file (cookiecutter.json). It takes a list of regular expressions. If a filename matches the regular expressions it will be copied and not processed as a jinja template.
Example
{
"project_slug": "sample",
"_copy_without_render": [
"*.js",
"not_rendered_dir/*",
"rendered_dir/not_rendered_file.ini"
]
}
This will not process any javascript files (files which end with .js), any files that are in the not_rendered_dir and not the not_rendered_file.ini in the rendered_dir. They will only get copied.

Just came across this question and also this Github Issue.
It seems like a nice addition, that one can partially mark parts of a file or entire template to not be processed by using the {% raw %} tag:
{% raw %}
{% comment %}Whatever jinja code goes here....{% endcomment %}
...
{% endraw %}

Related

{% translate s %} passed in {% include ... with s=s %} not in .po file

I have a basic feed I am trying to render in my Django project. I have created a feed.html file as a base template for slight variations of the same type of feed. Among those variations, is the header of the feed. Importantly, I want that header to be translated into multiple languages.
I have implemented this "variation" idea using {% include "feed.html" with variation=variation %}. However, I am having problems translating those variations.
I am trying the following in feed.html:
{% translate header %}
Then in one of the templates where I want a variation of feed.html I have:
{% include "feed.html" with header="Header" %}
The problem is, the string "Header" does not make it into any of my .po files and therefore remains untranslatable.
What am I doing wrong? Should I use different syntax?
The problem is, the string "Header" does not make it into any of my .po files and therefore remains untranslatable.
If that means that the makemessages command doesn't extract the string, then yes, it won't, because there is no string. Only a variable. That variable could take any value at all, makemessages cannot possibly trace that back to all possible locations where you might be setting the value for header. makemessages can only extract what you literally put into {% translate %} tags or _() function calls directly.
The caveat with using variables or computed values, as in the previous two examples, is that Django’s translation-string-detecting utility, django-admin makemessages, won’t be able to find these strings.
https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#standard-translation
You'll want to translate the header value before passing it:
{% include "feed.html" with header=_("Header") %}

Jinja2: Word experienced an error trying to open the file

I admit the question is vague, but that's the error I'm getting.
I'm trying to create a word document template using a derivative of the python-docx library called python-docx-template, which is using Jinja2.
What I'm doing is generating the data I need using Python, and then sending it to the docx template that I'm building, so that the document outputs the data in a format I want.
My Jinja2 template looks something like this:
{% if EXCHANGE_RATE %}
{%- for stringData in EXCHANGE_RATE %}
{{stringData}}
{%- endfor %}
{%- endif %}
Note that the template code is within a table cell. The entire data is supposed to be generated within the cell itself(ie. not separated by rows).
What is supposed to happen here is that the template checks for the existence of EXCHANGE_RATE list variable (because I may or may not return this data depending on situation) and then loops the data, resulting in something like this:
Exchange Rate:-
1 EUR= 1.0 USD
1 EUR= 1.0 GBP
For some reason, the if endif code seems to add some extra line spacing which I do not want(without it, the output is exactly what I want), hence the usage of the - at various parts.
The issue I have lies in the last line: {%- endif %}.
If I add an extra - at the back (like so {%- endif -%} ), it somehow causes an error whenever I generate and try to open the file, but I'm not exactly sure why.
I have a similar if endif nested for loop elsewhere and it will cause a similar issue, also at its own final {%- endif %} line.
Any suggestions?
Please note I'm still relatively new to Jinja2.
you can define the path of your word file in the trusted locations. for this purpose open MS word -> file -> options -> trust center setting -> trusted location -> add new location
and add the location the template is located in
after that you should not get word experienced error.
I hope :)
Try Edit from word file's context menu. Or you can disable protected view for all documents from Trusted Center settings at the end.

Django templates and whitespace

I started using custom inclusion tags within my django templates. For example I have a {% profilelink profile %} tag that inserts a link to a user profile together with a small version of the profile's picture, like so (profilelink.html):
<a href='{% url ... %}'><img src='{{ ... }}' alt='...'> {{ profile.name }}</a>
However, when I use it in the following snippet (sometemplate.html):
<p>Owned by {% profilelink owner %} (uploaded by {% profilelink uploader %})</p>
Then I get whitespace between the HTML produced by the second template tag and the closing parenthesis. This whitespace is unwanted. It comes from the final newline character in the file profilelink.html. This is a very common problem and searching Stackoverflow yields a lot of questions about whitespace in templates in general. Here's a summary of solutions found so far and why they don't work:
Some of these problems are solvable with the {% spaceless %} tag, but not all of them. This tag only removes whitespace between tags, which is not the case in the above example.
One possible solution is to not have a final EOL in profilelink.html but that's highly undesirable. Reasons: It is generally bad style; some editors (vim) silently add one back by default; that's how POSIX defines a line; it might make some SCMs unhappy; etc.
Another solution is switching to another template engine, like Jinja2, which may or may not solve this problem. It has support for constructs like {% ... -%} which eat the next EOL character. This is useful in some situations, but is also useless for my example above. But switching the templating backend for such a small annoyance seems a little overkill and adds another dependency. I'd like to stick to whatever is the standard "django" way of doing things. There are apparently plans to make Jinja2 the new Django default, though.
Some people suggested using a middleware class to remove redundant whitespace from the generated HTML before it's being sent to the browser. This is useful, but only for transforming the HTML in a way that is functionally equivalent, i.e. same semantics: it will then still be displayed the same way in the browser. That's not what I want, I want an actual change in semantics in order to have it display properly. This is impossible to implement in a generic middleware class. I need to have control over this on a case by case basis from within the template itself. I don't care about making the HTML prettier, I care about it being correct in the first place.
There's also bug #2594 which has been closed as WONTFIX with the argument (quote) "the Django template language is good enough for generating HTML, which isn't sensitive to whitespace". In my oponion this is just totally wrong. HTML is very much sensitive to whitespace, it just doesn't care how much there is of it. It cares a lot about whether there is some whitespace or none at all.
Some my question is: Is there any sane way to fix this problem in general? (One that always works, not just in some situations.)
(Any CSS-based fixes do not count. Copy/paste surprises are evil.)
I believe one solution is to use a simple_tag instead of an inclusion tag, hopefully without to much clutter.
I assume your tag is something like this:
#register.inclusion_tag('profilelink.html')
def profilelink(user):
return {"profile": user}
Would it be possible to substitute this with
from django.template.loader import render_to_string
#register.simple_tag
def profilelink(user):
t = render_to_string("profilelink.html", {"profile": user})
return t.strip()
I don't have a Django-project in front of me now, so this is untested.
This is the best I came up with so far. I still hope for a better solution, but for now it will do.
I defined a custom filter like this in base/templatetags/basetags.yp (taken from this answer):
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
#register.filter
#stringfilter
def trim(value):
return value.strip()
And then use it as follows:
{% load basetags %}
<p>Owned by {% profilelink owner %} (uploaded by
{% filter trim %}{% profilelink uploader %}{% endfilter %})</p>

What's the difference between the {% include ... %} tag and and the {% ssi ... parsed %} tag in Django templates?

They seem to be basically the same EXCEPT that you have to give ssi an absolute path for "security reasons". Except for keyword arguments (which are new since version 1.3), the two seem to have exactly the same capabilities. Are they really redundant?
Without the parsed parameter to {% ssi %} the included file won't be treated as a Django template, it will just be included as normal text. This means that if the included file had template tags/filters, they would not be interpreted.
When you do include the parsed parameter, the differences become more like what you said.
There's added security restrictions with {% ssi %} since you can potentially include any file on the filesystem.
You must use an absolute URI rather than a relative path suitable for a template loader.
Until Django 1.5, the first argument (the path) must be unquoted. This means you cannot use a template variable as the first argument.
There's more details on the last point in the documentation.

How come my template tag in Django doesn't work?

{% gen_aws "hello" %}
In my file, I do this:
#I want to add "goodbye" to every word passed to this tag.
#register.tag(name="gen_aws")
def gen_aws(s):
return s + "goodbye"
The .py file is fine...I'm including everything fine. I have other template "filters" in there that work fine. But then I added this in that file, and this template tag doesn't work.
Your description of "doesn't work" is not very accurate (to be exact it doesn't exist). But I guess you get an error because the tag is not found.
The documentation clearly states that you need a "templatetags" module in your app, with a submodule like "mytags", for example. Then you have to include these tags in each template you want to use them. You can do that with {% load mytags %}.
The "mytags" module then contains your "gen_aws" tag.
EDIT: The error "gen_aws() takes exactly 1 argument (2 given)" occurs because normal tags can parse their parameter in a very customized way. Therefore they get the arguments "parser" and "token". In your case, a so-called simple tag should be enough - Django then automatically parses parameters for you and passes them as Python values. So just replace #register.tag by #register.simple_tag.
Another possible cause of the "no attribute 'must_be_first'" error is that you've forgot to inherit from django.template.Node in your class. (Since this is pretty much the only Google result for that phrase I thought I'd add this here to save a couple of minutes for the next person.)

Categories

Resources