Syntax error whenever I put Python code inside a Django template - python

I'm trying to do the following in my Django template:
{% for embed in embeds %}
{% embed2 = embed.replace("<", "<") %}
{{embed2}}<br />
{% endfor %}
However, I always get an invalid block or some syntax error when I do anything like that (by that I mean {% %} code inside a loop). Python doesn't have {} to signify "scope" so I think this might be my problem? Am I formatting my code wrong?
Edit: the exact error is: Invalid block tag: 'embed2'
Edit2: Since someone said what I'm doing is not supported by Django templates, I rewrote the code, putting the logic in the view. I now have:
embed_list = []
for embed in embeds:
embed_list[len(embed_list):] = [embed.replace("<", "<")] #this is line 35
return render_to_response("scanvideos.html", {
"embed_list" :embed_list
})
However, I now get an error: 'NoneType' object is not callable" on line 35.

I am quite sure that Django templates does not support that.
For your replace operation I would look into different filters.
You really should try to keep as much logic as you can in your views and not in the templates.

Django's template language is deliberately hobbled. When used by non-programming designers, this is definitely a Good Thing, but there are times when you need to do a little programming. (No, I don't want to argue about that. This has come up several times on django-users and django-dev.)
Two ways to accomplish what you were trying:
Use a different template engine. See Jinja2 for a good example that is fully explained for integrating with Django.
Use a template tag that permits you to do Python expressions. See limodou's Expr tag.
I have used the expr tag in several places and it has made life much easier. My next major Django site will use jinja2.

I don't see why you'd get "NoneType object is not callable". That should mean that somewhere on the line is an expression like "foo(...)", and it means foo is None.
BTW: You are trying to extend the embed_list, and it's easier to do it like this:
embed_list = []
for embed in embeds:
embed_list.append(embed.replace("<", "<")) #this is line 35
return render_to_response("scanvideos.html", {"embed_list":embed_list})
and even easier to use a list comprehension:
embed_list = [embed.replace("<", "<") for embed in embeds]

Instead of using a slice assignment to grow a list
embed_list[len(embed_list):] = [foo]
you should probably just do
embed_list.append(foo)
But really you should try unescaping html with a library function rather than doing it yourself.
That NoneType error sounds like embed.replace is None at some point, which only makes sense if your list is not a list of strings - you might want to double-check that with some asserts or something similar.

Django templates use their own syntax, not like Kid or Genshi.
You have to roll your own Custom Template Tag.
I guess the main reason is enforcing good practice. In my case, I've already a hard time explaining those special templates tags to the designer on our team. If it was plain Python I'm pretty sure we wouldn't have chosen Django at all. I think there's also a performance issue, Django templates benchmarks are fast, while last time I checked genshi was much slower. I don't know if it's due to freely embedded Python, though.
You either need to review your approach and write your own custom templates (more or less synonyms to "helpers" in Ruby on Rails), or try another template engine.
For your edit, there's a better syntax in Python:
embed_list.append(embed.replace("<", "<"))
I don't know if it'll fix your error, but at least it's less JavaScriptesque ;-)
Edit 2: Django automatically escapes all variables. You can enforce raw HTML with |safe filter : {{embed|safe}}.
You'd better take some time reading the documentation, which is really great and useful.

Related

Why it is possible to use a split filter in ansible?

It might look like a weird question by, I really would like to understand this. I am new to Ansible, and I am trying to understand how I could figure out that I can use a filter called split. As I understand, the Ansible filters are builtin inside Jinja2 engine. On the project website there is nothing about split filter. I am really confused how come, it is possible to use split filter.
On Ansible website there is one mention about split
https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html
To split a string into a list:
{{ csv_string | split(",") }}
My question here is, how would I know that I can do | split(",",1)
that page does not explain that for example I could call a split filter with delimeter and a integer that describes how many times I want to split it.
Is there a different documentation, or a way to figure those things out on my own?
I was told that I could do in Python:
help(str.split)
And this explains me how to use split method, this is great however, how can I be sure that this is the same way of implementation as in the Ansible filter? Is this split filter from Ansible documentation inside 'Ansible' or inside Jinja? And maybe its just missing from documentation in Jinja website?
This doesn't explain where | split(",") is coming from but per the Jinja docs:
Python Methods
You can also use any of the methods defined on a variable’s type. The value returned from the method invocation is used as the value of the expression. Here is an example that uses methods defined on strings (where page.title is a string):
{{ page.title.capitalize() }}
So str.split() should also be valid syntax and work the same way.

Output all variables into Mako template

I don't have an easy access to the code, I'm working only with a Mako template, and I would like to know all the values that were made available to the template, which I can use.
Is there a way to add something in the template, so that the output result would contain all the variables (recursively)?
You're looking for the context object. After a minute or two of play:
${context.keys()} # list of direct variable names
${context.__dict__} # probably more along what you're looking for.
The entire section on the Mako Runtime environment is probably worth reading, especially the part 'All the built in names.' You may find the other post I just made relevant:
Mako how to check if variable exists or not.
Lets try this I think this must help:
${globals()}

performance of internationalized html templates

I'm writing a web application using Python and the Flask microframework. The application will support several languages, and I'm now trying to decide how to write i18n enabled html templates. My template engine is Jinja2 (though it is early enough in my project that I can switch to something else if necessary).
Let me start by showing an example portion of a template with gettext tags:
{% if error %}<div class="error">{{ _(error) }}</div>{% endif %}
<h1>{{ _("Hello, World!") }}</h1>
In this template there are two kinds of strings that the application will need to know how to translate:
dynamic strings that in the context of the template will only be known at runtime (the error string)
static strings that are known at any time (the "Hello, World!" string)
The first case is easy to handle. The string is passed to the gettext engine at runtime to obtain the translated version. No issues there.
While the second case can be handled in the same way, my impression is that there's got to be a more efficient way to handle these static strings. None of the documentation I read for gettext, Babel or Jinja2 mention anything about optimizing the translation of static strings that will have to be searched and located every time the template needs to be rendered.
An approach that I think makes a lot of sense is to pre-render each template into a set of language specific sub-templates, where each sub-template has the static strings resolved, leaving only the dynamic text sections for gettext to handle at runtime.
So, for example, if I wanted to support English and Spanish, my template above would be processed offline by some tool that will generate two sub-templates that will get written to a template cache:
template-en.html:
{% if error %}<div class="error">{{ _(error) }}</div>{% endif %}
<h1>Hello, World!</h1>
template-es.html:
{% if error %}<div class="error">{{ _(error) }}</div>{% endif %}
<h1>¡Hola, Mundo!</h1>
Then at runtime the template engine needs to check if a specific sub-template for the requested locale is available in the cache, and if one is found then rendering will be much faster.
Are there any frameworks, tools, template engines, etc. that implement something like this?
Or are there any other ways to avoid the overhead of searching the translation database for the same little snippets of text over and over again?
Have you measured the impact of such an "optimization" on the whole request-response cycle? I'd be very surprised if you would see any meaningful speedups, especially when using a template language that is already known to be pretty darn fast, like Jinja2.
As a general rule: never optimize before having measured the potential gains of the optimization. Intuition is oftentimes completely wrong in this area. This is especially true when an optimization introduces complication in code, development or deployment - always measure if it is worth the hassle.
You'd probably have more success looking into optimizing database queries or caching of expensive operations (a dict lookup, which gettext basically is, is not expensive at all).
You're doing it wrong. You should never I18Nize variables (your first type), only static text (your second type). You need to I18Nize the strings that could be used in error, not the variable itself.
And optimization should be done at the message catalog (gettext) level, not in your code.

Django Template Arithmetic

In my template, I am looping through a list, trying to make a two-column layout. Because of the desired two-column layout, the markup I need to write in the for loop is dependent on whether forloop.counter0 is even or odd. If I had the full power of Python in the template language, determining the parity of forloop.counter0 would be trivial, but unfortunately that is not the case. How can I test whether forloop.counter0 is even or odd using the Django template language, or just as good, is there another way I could get elements in the list to display alternatively in the left and right columns?
Thanks in advance!
You should probably use cycle here instead. As for your question, there is a filter called divisibleby.
The philosophy behind Django's template system is to avoid doing any serious logic in the template. Thus they only provide tools to do fairly basic calculations for cases like drawing grids etc.
You can use the divisibleby filter with forloop.counter:
{% if forloop.counter|divisibleby:"2" %}even{% else %}odd{% endif %}
Use cycle template tag:

Better error reporting mako

Is there a way to add tempate string which contains error to mako`s error trace?
I don't think you're likely to find such a thing. Like all the other fast python template engines, Mako achieves its speed by compiling your template into python code and then executing it. An exception will divert execution out of your template's code, so by the time one is raised, that template will have no way of displaying it (or doing anything else for that matter).
As an alternative, I suggest putting your template rendering code inside a try block, and rendering any caught exceptions with a separate template used specifically for that purpose.
I was looking for another error I have and found this. I though it would be nice if you still ever need this, you can achieve it by setting mako.strict_undefined = True. I am using mako-0.6.2 so it may not been possible in the version back in 2010.

Categories