I'm using Django Messaging framework to send additional data on the validation error:
def clean_X(self):
xuser_id = self.cleaned_data['xuser_id']
if xuser.objects.filter(xuser_id=xuser_id).exists():
available_now = {"available" : ["example","hello","ahc","sdcsd"]}
messages.error(self.request, message = available_now,extra_tags="available_ids")
raise forms.ValidationError('Sorry! User ID "%(xuser_id)s" is already taken, Please try another or chose one from following:', params={"xuser_id" : xuser_id})
return xuser_id
The message is converted as a string when tried to access in the template: like
"{"available" : ["example","hello","ahc","sdcsd"]}"
making difficult to access programmatically i.e message.available
How can i send a json directly to the template using Django-Messages. My intention is here, not just to display a message rather make available-id's clickable (like the one in gmail auto-suggestion of username)
Thanks!
{% for message in messages %}
<p>{{ message.tags }}</p>
{% if message.tags == 'available_ids error' %}
{% for obj,values in message.message.items %}
<div>
{{ obj }}
{% for val in values %}
<p class="user-id">{{ val }}</p>
{% endfor %}
</div>
{% endfor %}
{% endif %}
{% endfor %}
You can use above code snippet inside template to make it working and modify it according to your requirements.
How it works?
We iterate through each and every message, as we have inserted dictionary in messages so we have to iterate dictionary and inside dictionary we have list so we have to iterate that too.
Therefore we have to use three for loop.
You have to apply some conditions like when you have to iterate? You can check using this by tags.
Here I have hard coded (iterating condition) for this purpose.
Edit:
Using two for loops
Update your clean_X with these lines
available_now = ["example","hello","ahc","sdcsd"]
messages.error(self.request, message = available_now,extra_tags="available_ids")
and use these lines in templates
{% for message in messages %}
<p>{{ message.tags }}</p>
{% if message.tags == 'available_ids error' %}
<div>
{% for val in message.message %}
<p class="user-id">{{ val }}</p>
{% endfor %}
</div>
{% endif %}
{% endfor %}
Related
I am newbie in django. How can I concat string in a for loop in django template
{% for lead in project.leaders %}
{% if forloop.counter == 1 %}
{% lead_member = lead.0 %}
{% else %}
{% lead_member = ','.lead.0 %}
{% endif %}
{{ lead_member }}
{% endfor %}
Finally my lead_member should be test1,test2,test3....
what is happening now (my current code)
{% for lead in project.leaders %}
{{ lead.0}}
{% endfor %}
and the output is test1test2test3.... but i want to make same as test1,test2,test3....
Try this. it works
{% for lead in project.leaders %}
{{ lead.0 }}{% if not forloop.last %}, {% endif %}
{% endfor %}
There's no need to assign anything, nor do you need that type of complexity by using assignment tags. To keep your templating stupid-simple, you could always do this in your view, or even at the model level:
# don't step on the `join` built-in
from django.template.defaultfilters import join as join_filter
class Project(models.Model):
#property
def leaders(self):
return join_filter(self.objects.values_list('some_field', flat=True), ', ')
Then all you have to do in the template is:
{{ project.leaders }}
It's hard to understand your question, but I hope i did it. There is a number of related questions such as String-concatination,
How to concatenate in django
It's possible to create first string, concatinate it with comma and new string for every iteration. You are also able to make smth like ','.join(list_of_strings) on your server side before rendering. You can also join your list in templating by {{ list|join:", " }}.
I have a list say list[a][b] of length 10.
I want to print from list[0][b] to list[10][b] and use it in jinja2 template.
{% for i in test %}
<p> {{test[i][0]}} </p>
{% endfor %}
throws error:
UndefinedError: list object has no element
You actually get the element out of the list when you iterate over it, not the index value:
{% for row in test %}
{# Note that we subscript `row` directly,
(rather than attempting to index `test` with `row`) #}
<p>{{ row[0] }}</p>
{% endfor %}
If you want to make sure to always have the first 10:
{% for test in tests[0:10] %}
<p> {{ test[1] }} </p>
{% endfor %}
I have the following code, written inside a Django template.
{% if user.is_authenticated %}
<div style="float: right;">
{% for rel in RELATIONS %}
{% if rel.group_id == g.id %}
Unsubscribe
{% endif %}
{% else %}
Enrol
{% endfor %}
</div>
{% endif %}
The purpose of the code is to check if there is a match and then print out the unsubscribe tag. If there is not match print out the subscribe tag.
The reason I am having trouble doing this is because you in Django templates, I read that you can't have variables (i.e. a True or False).
UPDATE: (The question)
I want to only print out the Unsubscribe/subscribe button once. Print out the unsubscribe button only if there is a match inside the for loop. Otherwise print out the subscribe button if there is no match (i.e. no match at all for rel.group_id == g.id )
UPDATE 2:
While doing some research earlier I found this: https://code.djangoproject.com/ticket/3481
This might add some context to my problem.
Thank you for your help.
Seems like your if/else/endif are mixed up. Try
{% if user.is_authenticated %}
<div style="float: right;">
{% for rel in RELATIONS %}
{% if rel.group_id == g.id %}
Unsubscribe
{% else %}
Enrol
{% endif %}
{% endfor %}
</div>
{% endif %}
UPDATE
You want to check if g is in relations and make your decission based upon that.
The way I usually solve this is to create a function in my view that does this check and passes that allong to the view. Have a look here.
I am already trying to concatenate like this:
{% for choice in choice_dict %}
{% if choice =='2' %}
{% with "mod"|add:forloop.counter|add:".html" as template %}
{% include template %}
{% endwith %}
{% endif %}
{% endfor %}
but for some reason I am only getting "mod.html" and not the forloop.counter number. Does anyone have any idea what is going on and what I can do to fix this issue? Thanks alot!
Your problem is that the forloop.counter is an integer and you are using the add template filter which will behave properly if you pass it all strings or all integers, but not a mix.
One way to work around this is:
{% for x in some_list %}
{% with y=forloop.counter|stringformat:"s" %}
{% with template="mod"|add:y|add:".html" %}
<p>{{ template }}</p>
{% endwith %}
{% endwith %}
{% endfor %}
which results in:
<p>mod1.html</p>
<p>mod2.html</p>
<p>mod3.html</p>
<p>mod4.html</p>
<p>mod5.html</p>
<p>mod6.html</p>
...
The second with tag is required because stringformat tag is implemented with an automatically prepended %. To get around this you can create a custom filter. I use something similar to this:
http://djangosnippets.org/snippets/393/
save the snipped as some_app/templatetags/some_name.py
from django import template
register = template.Library()
def format(value, arg):
"""
Alters default filter "stringformat" to not add the % at the front,
so the variable can be placed anywhere in the string.
"""
try:
if value:
return (unicode(arg)) % value
else:
return u''
except (ValueError, TypeError):
return u''
register.filter('format', format)
in template:
{% load some_name.py %}
{% for x in some_list %}
{% with template=forloop.counter|format:"mod%s.html" %}
<p>{{ template }}</p>
{% endwith %}
{% endfor %}
You probably don't want to do this in your templates, this seems more like a views job: (use of if within a for loop).
chosen_templates=[]
for choice in choice_dict:
if choice =='2':
{% with "mod"|add:forloop.counter|add:".html" as template %}
template_name = "mod%i.html" %index
chosen_templates.append(template_name)
Then pass chosen_templates to your template where you will have only
{% for template in chosen_templates %}
{% load template %}
{% endfor %}
Also, I don't quite understand why you are using a dict to select the template with a number that is not in the dictionnary. for key,value in dict.items() may be what you are looking for.
Try without using the block "with"
{% for choice in choice_dict %}
{% if choice =='2' %}
{% include "mod"|add:forloop.counter|add:".html" %}
{% endif %}
{% endfor %}
I want to put break and continue in my code, but it doesn't work in Django template. How can I use continue and break using Django template for loop. Here is an example:
{% for i in i_range %}
{% for frequency in patient_meds.frequency %}
{% ifequal frequency i %}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}" checked/> {{ i }} AM</td>
{{ forloop.parentloop|continue }} ////// It doesn't work
{ continue } ////// It also doesn't work
{% endifequal %}
{% endfor%}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}"/> {{ i }} AM</td>
{% endfor %}
Django doesn't support it naturally.
You can implement forloop|continue and forloop|break with custom filters.
http://djangosnippets.org/snippets/2093/
For-loops in Django templates are different from plain Python for-loops, so continue and break will not work in them. See for yourself in the Django docs, there are no break or continue template tags. Given the overall position of Keep-It-Simple-Stupid in Django template syntax, you will probably have to find another way to accomplish what you need.
For most of cases there is no need for custom templatetags, it's easy:
continue:
{% for each in iterable %}
{% if conditions_for_continue %}
<!-- continue -->
{% else %}
... code ..
{% endif %}
{% endfor %}
break use the same idea, but with the wider scope:
{% set stop_loop="" %}
{% for each in iterable %}
{% if stop_loop %}{% else %}
... code ..
under some condition {% set stop_loop="true" %}
... code ..
{% endif %}
{% endfor %}
if you accept iterating more than needed.
If you want a continue/break after certain conditions, I use the following Simple Tag as follows with "Vanilla" Django 3.2.5:
#register.simple_tag
def define(val=None):
return val
Then you can use it as any variable in the template
{% define True as continue %}
{% for u in queryset %}
{% if continue %}
{% if u.status.description == 'Passed' %}
<td>Passed</td>
{% define False as continue %}
{% endif %}
{% endif %}
{% endfor %}
Extremely useful for any type of variable you want to re-use on template without using with statements.