how to run this code in django template - python

this is my code :
{% for i,j in enumerate(a) %}
{{i}} ,{{j}}
{% endfor%}
but , it show a error , i think it cant run the enumerate method ,
so how to run the enumerate in django template ,
thanks

The template subsystem has some special constructs built into the for/endfor block that allows you to access the current index of the loop without having to call enumerate.
{% for j in a %}
{{ forloop.counter0 }}, {{ j }}
{% endfor %}
While this snippet solves your immediate problem, if you're expecting to have access to Python builtins and other Python constructs inside your Django templates, you may be misunderstanding the sandbox that it provides/enforces.

you can use {{ forloop.counter }} or {{ forloop.counter0 }} for the same effect, the latter is 0-indexed, thus more like enumerate.

{% for item in a %}
{{ forloop.counter }}, {{ item }}
{% endfor %}
Link related

Django template makes up the presentation layer and are not meant for logic. From the docs
If you have a background in programming, or if you’re used to languages which mix programming code directly into HTML, you’ll want to bear in mind that the Django template system is not simply Python embedded into HTML. This is by design: the template system is meant to express presentation, not program logic.
Now to get the same functionality in Django, you will have to complete your logic in the views.
views.py
def my_view(request, ...):
....
enumerated_a = enumerate(a);
....
return render_to_response('my_template.html', {'enumerated_a ': enumerated_a }..)
Now enumerate function returns an enumerate object which is iterable.
my_template.html
{% for index, item in enumerated_a %}
{{ index }},{{ item }}
{% endfor %}
Although I think you can probably change it to an enumerated list and use it like that as well.

If however you need to use a function within a template, i suggest you create a filter or a tag instead. For reference, check out http://docs.djangoproject.com/en/1.2/howto/custom-template-tags/

Related

Assign multiple variables in a with statement after returning multiple values from a templatetag

Is there a way to assign multiple variables in a with statement in a django template. I'd like to assign multiple variables in a with statement after returning multiple values from a templatetag
My use case is this:
{% with a,b,c=object|get_abc %}
{{a}}
{{b}}
{{c}}
{% endwith %}
I don't think it's possible without a custom templatetag.
However if your method returns always the same length you can do it more compact like this:
{% with a=var.0 b=var.1 c=var.2 %}
...
{% endwith %}
I'm not sure that this as allowed, however from docs multiple assign is allowed.
But you can assign these 3 variables to 1 variable, which will make it tuple object, which you can easily iterate by its index.
{% with var=object|get_abc %}
{{ var.0 }}
{{ var.1 }}
{{ var.2 }}
{% endwith %}
Its not supported and its not a flaw of Django Template Language that it doesn't do that, its Philosophy as stated in the docs:
Django template system is not simply Python embedded into HTML. This
is by design: the template system is meant to express presentation,
not program logic
What you could do is prepare your data on Python side and return appropriate format which will be easy to access in template, so you could return a dictionary instead and use dotted notation with key name:
{# assuming get_abc returns a dict #}
{% with var=object|get_abc %}
{{ var.key_a }}
{{ var.key_b }}
{{ var.key_c }}
{% endwith %}

How to achieve list Iteration in django template [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Get list item dynamically in django templates
How to get list items with variable counter. The aim is to get the so item instead of list
not like this
{% for item in listModels %}
{{ item | safe }}
{% endfor %}
so work
{% for i in listModels|length|get_range %} // get size list
{{ listModels.i | safe }}
{% endfor %}
do not work
{% for i in listModels|length|get_range %} // get size list
{{ listModels.i | safe }}
{% endfor %}
Django templates will not allow you to do this. I'm not going to lecture you on keeping your logic out of your templates, because I think it's a stylistic choice. But understand that this is the easiest way. If you need to use the index, you can access it as a forloop property, as explained in the documentation.
If you really want variable indexing, you could make your own custom template tag to do it. But, in this case, I suggest you use a more powerful templating language, like Jinja2, instead of torturing the Django templating language.
Django Template Language provides you a way to do this...
{% for item in listModels %}
{{ forloop.counter }}
{% endfor %}
I fixed like I did the following:
{{ listModelsData|lookup:i|lookAttribute:"author" }} -// this equal listModelsData[i].author - this code in python
#register.filter
def lookAttribute (d, token):
     return getattr (d, token)

jinja2: macro selecting macro or dynamic macro calls

I have a list of namedtuples I'm going through, each slightly differing in rendering requirements, so I want to call the proper macro based on an attribute. What I have is this:
{% macro format_item(item) %}
{% if item.type_of == 'a' %}
{{ format_a(item) }}
{% elif item.type_of == 'b' %}
{{ format_b(item) }}
{% elif item.type_of == 'c'%}
{{ format_c(item) }}
{% elif item.type_of == 'd'%}
{{ format_d(item) }}
{% else %}
{{ format_general(item) }}
{% endif %}
{% endmacro %}
but what I want is to something like:
...iterating through list of items
{{ call macro based off item.type_of }}
at this point in regular python I'd do something like
getattr(object_with_method_to_produce_templates, item)
but haven't figured out a way to use the attr filter effectively (if I can use it properly in this situation at all).
I've found flask.get_template_attribute looking elsewhere which might be interesting (if I can instead just do it all ahead of time and send a precalculated and preformatted item to the template). Maybe too much and beyond what I want to do at this time.
What is a better way to call from a varied listing of macros instead of a list of if then's that might get rather large in the future? Seems like a common question, but I have not stumbled on the exact answer I'm looking for.
EDIT:
I added this to what I was doing, trying to generate a callable macro as part of the item I want to render
from flask import get_template_attribute
from jinja2 import Template
test_template = Template('{% macro test_macro(item) %}<div id="test-div">sent to me: {{ item }}</div>{% endmacro %}')
...in item generation...
template = get_template_attribute(test_template, 'test_macro')
...in template...iterate items then for each item
{{ item.template("testing this method") }}
which sort of works but only generates the string letter for letter, not as a regular macro would(i.e. the divs aren't rendered as divs, only as text).
<div id="test-div">sent to me: testing this method</div>
So I need to give Template some context, or something this is closer to what was aiming for but doesn't seem right.
EDIT2:
{{ item.template("testing this method")|safe }}
returns what I was looking for, so this is passable, I might be able to bypass the namedtuple arrangement I had and just pass a macro with...more working on it I suppose. Is this optimal/preferable or a mess though?
You can create a Jinja2 filter which gets the Macro from the current context and then evaluates the Macro. The filter is:
#contextfilter
def call_macro_by_name(context, macro_name, *args, **kwargs):
return context.vars[macro_name](*args, **kwargs)
See the full answer here.

Python/Django: Simple Django Template

Hi I am using App Engine/Python to do a simple website. I have some trouble with a Django template problem.
In short, I want to use a "ShortName" to access a "LongName".
The soource code:
LongName={"so":"stackoverflow","su":"superuser"}
ShortName=['so','su']
Then I pass these two parameters to the templates.
In the template I write:
{% for aname in ShortName %}
{{ aname }} stands for {{ LongName.aname }},
{% endfor %}
The output is:
so stands for, su stands for
No error is given. The LongName.aname wont work.
I have no idea whats wrong.
This is trying to access LongName['aname'], not LongName[aname].
You might have to write a custom template tag/filter to get this to work. This Django bug (marked WONTFIX) has a simple implementation:
def get(d, key):
return d.get(key, '')
register.filter(get)
which you would use by
{{ LongName|get:aname }}
after adding it to your app (that SO answer shows how to do it on GAE).
You could also pre-make a variable to loop over in the view, by passing in
# in view
name_abbrevs = [(k, LongName[k]) for k in ShortName]
# in template
{% for short_name, long_name in name_abbrevs %}
{{ short_name }} stands for {{ long_name }}
{% endif %}
If you really don't want to add a template tag -- which isn't that bad! you just make one file! :) -- or pass in an extra variable, Vic's approach will let you do this without touching the Python files at all. As he mentions, it involves a lot of pointless iteration, but it'll work fine for small lists.
Django templates have a drawback here. I've been in the same situation before. What you have to do is iterate over all the keys in LongName, and check if the key you're looking for matches the ShortName. Here you go:
{% for aname in ShortName %}
{% for short_version, long_version in LongName %}
{% if aname == short_version %}
{{ aname }} stands for {{ long_version }},
{% endif %}
{% endfor %}
{% endfor%}
It's inefficient, and essentially a pointless O(n^2) mechanism. However, there's no better way in pure Django templates to refer to entries of a dict by a variable name.

Django templates: accessing the previous and the following element of the list

I am rather new to django templates and have an impression that I have not understood some basics.
I have a list of elements and I need to render an element of the list based on conditions against the the previous and the next elements (in case the following or the previous elements are hidden, I need to mark the current element as border element).
How can I reference the previous and the following elements within a for loop in Django templates?
You could write a custom template filter for next and previous:
def next(value, arg):
try:
return value[int(arg)+1]
except:
return None
and in the template:
{% for ... %}
{% with list|next:forloop.counter0 as next %}
{% if next.is_hidden %}
...
{% endif %}
{% endwith %}
{% endfor %}
but like others have said, there are probably more elegants solutions doing this via your view
You can't do this strictly with built-in template tags. You need to involve some Python.
One method would be to zip the list with itself:
new = ([(None, orig[0], orig[1])] +
zip(orig, orig[1:], orig[2:]) +
[(orig[-2], orig[-1], None)])
and pass that to the template, then loop over it like this:
{% for prev, current, next in new %}
{% if prev.hidden or next.hidden %}
BORDER
{% endif %}
{{ current }}
{% endfor %}
You really shouldn't use the Django templates for this kind of logic. You have your views to handle it. I would figure out which elements of the list are borders and pass in an extra parameter that I can handle in the template using a simple if statement. For example:
{% for element,is_border in data.items %}
{% if is_border %}
do something
{% endif %}
{% endfor %}
There are tons of similar ways you can do this. I presented just one example.
You can create an external tag which does that but django templating system which was build to be lightweight has no such feature in for loops.

Categories

Resources