views:

1587

answers:

5

I'm trying to do the following in my Django template:

    {% for embed in embeds %}
        {% embed2 = embed.replace("&lt;", "<") %}
        {{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("&lt;", "<")] #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.

+6  A: 

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.

kigurai
You could rewrite your answer to be a little stronger. Processing in templates is intentionally forbidden. You must do all processing in your view functions.
S.Lott
...or in custom template tags and template filters.
insin
+2  A: 

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("&lt;", "<"))

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.

vincent
+2  A: 

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.

lacker
+3  A: 

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("&lt;", "<")) #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("&lt;", "<") for embed in embeds]
Ned Batchelder
That list comprehension is so much nicer for my eyes :)
kigurai
+4  A: 

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.

Peter Rowell