Tag inside tag Django template - python

First of all, let me show our views.py file.
context = {
'id' : id,
'durum' : durum,
'range': range(len(id)),
}
I have such data in template;
context.id = [12, 10, 10]
context.durum = ['UPL','PPL','FIUPL']
I want to match this data like this;
12 UPL
10 PPL
10 FIUPL
I created a for loop for this, but need to edit
{% for i in context.range %}
{{ context.id }}
{{ context.durum }}
{% endfor %}
Like this;
{% for i in context.range %}
{{ context.id.i }}
{{ context.durum.i }}
{% endfor %}
But I can't use the variable i in the loop.

Use zip in view
Ex:
context = {
'data' : zip(id, durum)
}
And then in template
Use:
{% for id, durum in data %}
{{ id }}
{{ durum }}
{% endfor %}

You can use list comprehension.
So, for example:
my_list = list(zip(context['id'], context['durum'], context['range']))
And then in the template, you can use:
{% for item in my_list %}
{{ item.0 }} -- { item.1 }}
{% endfor %}

Well, it seems like you moved to python from some other language. You don't usually use indexing in python for loops (they are much easier and more intuitive) that's why it was hard for you to 'pair' those values. If you still can refactor your code, instead of making to list with attributes on matching indexes use a dict. One - it will let you unpack really easily in django template
{% for id, durum in my_dict %}
{{ id }} {{ durum }}
{% endfor %}
Two - it will prevent any errors connected with wrong index because you just call id and it will get the right durum. Three - it will be very easy to update such data set.
my_dict.update({new_id: new_durum})
Please consider spending a little bit of time learning new stuff because it will make your python experience much more pleasureable. Oh and btw - most of time you dont have to specify the {{ context.something }} call - its enough to call {{ something }}

Related

adding an integer postfix or prefix to an html attribute with flask-wtforms

I have the following thing in a jinja2 for loop:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal' }) }}
I need to have an index on the data-target like:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-item' }) }}
item is the index needed in this case. Is there a way to escape item out of this "ad-hoc dictionary"? So that it takes on the same values as in meal[item]?
I need the 'data-target' attribute to render as '#myModal-0', '#myModal-1', etc.. As it stands each 'data-target' attribute gets set as '#myModal-item' for each item in the loop. In other words it sets item in the second line of code as a string.
In case it is ever helpful for someone, what wound up solving my problem was:
<form method="POST">
{{ meal[item]['open-modal'].csrf_token }}
{{ meal[item]['open-modal'].submit( **{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-' +
item|string } ) }}
</form>
Keep in mind that this is nested inside of two for loops in jinja2.
{% for meal in menu_dict %}
{% for item in meal %}
....
{% endfor %}
{% endfor %}
The point is summarized with this, basically:
'data-target':'#myModal-' + item|string
adds the postfix.

Django loop variable as key

i am new to django and tried to use the variable of an loop as a key for another object:
this is my views.py
...
files = Files.objects.filter(dataset__id = instance.dataset.id)
context = {'files': files, 'range': range(files.count())}
return render_to_response("test.html", context, context_instance=RequestContext(request))
and my test.html looks like this:
{% for i in range %}
<img title="{{i}}" src="{{files.i.data_files.url}}"/>
{% endfor %}
if i use files.0.data_files.url (or 1,2,3..) instead of files.i. it works, but i want to give out all images and also need the position of the image.
can you help me please?
the thing you're probably looking for is a magic variable {{ forloop.counter }} (or {{ forloop.counter0 }} if you want to use zero-based index) available inside {% for %} loop:
{% for file in files %}
<img title="{{ forloop.counter }}" src="{{file.data_files.url}}"/>
{% endfor %}

create templates on the fly / dynamically

I am currently writing a django app around a rather complex data model.
For many use cases, I need to build similar, but slightly differing templates (incl. graphviz etc..).
Now I wonder if there is a way to follow DRY and create the templates "on the fly", e.g. based on a nested tuple (of which one gets defined per use-case -> template).
Practically speaking I'd like to stop writing these:
static_template_case1.html
{% if program %}
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
{% endif %}
and replace it with something in the following direction:
template_generator.py
structure_case1 = ("program"("process"("step","control")))
def onTheFlyTemplate(structure):
# iterate through structure
# build template dynamically
# return template
onTheFlyTemplate(structure_case1)
I was not able to find something similar and also don't know yet where to start generating templates on the fly, nor how to integrate it.
Within the views feels like a good starting point, (instead of loader.get_template('static_template_case1.html')).
Thanks for any hint sending me into the right direction as well as your thoughts if DRY is being "overdone" here.
Ralph
Edit
I got a step closer, doing the following:
In the view:
from django.template import Template
def templateGen():
return Template("Program: {{program.count}}")
#login_required
def test(request):
program = Program.objects.all()
t = templateGen()
c = RequestContext(request,locals())
return HttpResponse(t.render(c))
So far this is only a proof of concept. The real work will be to write a smart "templateGen()" listening to the nested tuple.
How about an inclusion tag?
#register.inclusion_tag('<your-template.html>')
def get_program(program_id):
return {'program': <some logic to return your Program object>}
Your main template:
{%load my-template-tags%}
<div id="my-div">
{%get_program program_id %}
</div>
And your template file:
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
You'd have to pass in your program_id to the main template.

django template filters change order of evaluation

Is there a way to change the order django evaluates a template filter ?
Say i have
{{ 3|add:5|multiply:"10" }}
Right now his adds 3+5 and multiplies the result times 10.
What i am looking for is a way of doing the following:
{{ 3|add:(5|multiply:"10") }}
As you can see i wrapped the 5|multiply:"10" in parenthesis to emphasize that it should be evaluated before the |add. Is this possible ?
You have two possibilities:
You could change the order of filters/values:
{{ 5|multiply:10|add:3 }}
Or You could use {% with %}:
{% with temp=5|multiply:10 %}
{{ 3|add:temp }}
{% endwith %}

using "range" in a google app engine template for - loop

i've got an appengine project and in my template i want to do something like
{% for i in range(0, len(somelist)) %}
{{ somelist[i] }} {{ otherlist[i] }}
{% endfor %}
i've tried using 'forloop.counter' to access list items too, but that didn't work out either. any suggestions?
regards, mux
What you might want to do instead is change the data that you're passing in to the template so that somelist and otherlist are zipped together into a single list:
combined_list = zip(somelist, otherlist)
...
{% for item in combined_list %}
{{ item.0 }} {{ item.1 }}
{% endfor %}

Categories

Resources