Can you declare multiple with variables in a django template? - python

I know it's not good practice, but is there a way to declare multiple variables in a with statement in a django template.
For example I want to do something like this:
{% with a="a", b="b", c="c" %}
{{a}}
{{b}}
{{c}}
{% endwith %}
Edit
My actual use case is this:
{% with a,b,c=object|get_abc %}
{{a}}
{{b}}
{{c}}
{% endwith %}
Edit 2
New Question for first Edit: Assign multiple variables in a with statement after returning multiple values from a templatetag

The example on the doc page clearly states that you can assign more than one variable, but you wouldn't need those commas:
{% with alpha=1 beta=2 %}
...
{% endwith %}
Reference:
with template tag

Related

Assign a value to a variable already declared in the template in django?

I googled but unable to find the solution. Where I went thought some answers like This answer
Some official docs which I went through Trans Tag Built-In Tags
Template View
{% load custom_tags %}
{% for each in content %}
{% with tempID='' %} # It is initially empty string
{% if each.contentID != tempID %}
{% tempID = each.contentID %} # Want to assign new value to tempID
....
..
{% endif %}
{% endwith %}
{% endfor %}
Is there any method to assign with tag variable. I tried custom_tags filters also. Not worked.
Is there any method to assign with tag variable?
Yes, you can simply use the {% with tempID= each.contentID %} which in this case will assign a new value to the variable.
Alternative
Variables in templates are merely used to display values and are not often used in a way in which calculation or reassignment is performed. In such cases though you can solve it by using a Django custom filter. See the example below.
.py file - Assign a value to a variable
#register.filter(name='update_variable')
def update_variable(value):
data = value
return data
.HTML file
{% with "true" as data %}
{% if data == "true" %}
//do somethings
{{update_variable|value_that_you_want}}
{% else %}
//do somethings
{% endif %}
{% endwith %}
Note that when you are using Django filters the variable instance resides in Python and not directly in the Template.

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 %}

Django use value of template variable as part of another variable name

I currently have this for loop inside my template:
{% for i in 1234|make_list %}
I would like to obtain something like this inside loop:
{{ form.answer_{{ i }} }}
I am aware that the above line is not valid (it raises TemplateSyntaxError), but I would like to know if there is any way to use the value of i as part my other variable name.
First, you would need a custom template filter to mimic getattr() functionality, see:
Performing a getattr() style lookup in a django template
Then, you would need add template filter for string concatenation:
{% load getattribute %}
{% for i in 1234|make_list %}
{% with "answer_"|add:i as answer %}
{{ form|getattribute:answer }}
{% endwith %}
{% endfor %}

How to get with statement working with zinnia tag

I got a problem with iteration on zinnia tag outcome. Let's say that that tag returns a list of some categories, I tried to manage it in few ways:
{% with categories=get_plain_categories %}
{% for category in categories %}
<h1>{{ category }}</h1>
{% endfor %}
{% endwith %}
or simply:
{% for category in get_plain_categories %}
<h1>{{ category }}</h1>
{% endfor %}
But in both ways, it seems to not even run get_plain_categories tag (I made few prints in it), but when I write : {% get_plain_categories %}, it returns list as it's supposed to.
How should I get that working?
Unfortunatelly with tag is not that powerful, you can't use it with output of other tags. You'll have to create your own tag.
As an example you can have a look at the static. It lets you insert a path to a static file with {% static "images/hi.jpg" %} but you can't easily save it to a variable for later use. That's why in Django 1.5 it got a new syntax {% static "images/hi.jpg" as myphoto %} and this way you can later use {{ myphoto }}. This can't be achieved with with.
That said, I can't find any mentions of get_plain_categories in Google, which is weird.

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