This is my template tag in a forloop
{{ product.feature_set.all.1.value }}
i want to change the number 1 to the forloop.counter. is this posible?
like:
{{
product.feature_set.all.forloop.counter.value
}}
It does not work like that, but is there a way to do this?
This doesn't make sense. You should be looping through the queryset itself.
{% for feature in product.feature_set.all %}
{{ feature }}
{% endfor %}
Since #Daniel's answer doesn't satisfy you, I thought you might want to try writing a custom filter. Here is a rough draft:
#register.filter
def custom_m2m(queryset, forloop_counter):
return queryset[forloop_counter].value
You can use it in your template like this:
{% for ... %}
{{ product.feature_set.all|custom_m2m:forloop.counter }}
{% endfor %}
Related
Here's what I'm trying to achieve in "pseudo code":
{% for page in pages %}
{% if 'can_access_page_{{page.name}}' in perms %}
<li>
{{ page.name }}
</li>
{% endif %}
{% endfor %}
How to do this? Permission names I can customize — but still can't figure out this one.
Simplest way is to slightly abuse Django's existing add template filter (intended for numbers but works for strings), as in this answer:
https://stackoverflow.com/a/4524851/202168
You'll need a custom filter. Something like:
#register.filter
def check_page_perms(page, perms):
return 'can_access_page_%s' % page.name in perms
and use it:
{% if page|check_page_perms:perms %}
In my Django template as I am iterating through a list of objects, I'd like to have one list item say:
<li>Blah</li>
and then another do:
<li>Blah</li>
I see value|random as an option but for some reason this doesn't work:
{% ifequal [1, 2]|random 1 %}
{{ post.title }}
{% else %}
{{ post.title }}
{% endifequal %}
Doing this throws this error:
u'ifequal' takes two arguments
Is there any way to accomplish this? I would think it should be simple but I realize the Django templating language doesn't allow for variable assignments.
Thanks!
You can't put a list directly into the template like that, make_list is what you're after.
make_list returns a list of strings, so this would work.
{% if 12|make_list|random == '1' %}
<li>Blah</li>
{% else %}
<li>Blah</li>
{% endif %}
I want to create such loop:
{% for object in objects %}
{% if object.before != object %}
{{ object }} this is different
{% else %}
{{ object }} this is the same
{% endfor %}
Based on https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for I can't. Is there really no simple way to do this? Or I just need to use counter and check for objects[counter-1]?
P.S. .before is theoretical and objects is simple query list. I want to take and do something with the loop member that encountered before current loop member.
Check ifchanged template tag
There is a "simple way" to do this: write a custom template tag. They're really not hard. This would probably do the trick (untested):
#register.simple_tag
def compare_objects(object_list):
comparisons = []
for i in range(1, len(object_list)):
if object_list[i] > object_list[i-1]:
comparisons.append('bigger')
else:
comparisons.append('smaller')
return comparisons
The built-in template tags and filters don't make it easy (as of Django 1.4), but it is possible by using the with tag to cache variables and the add, slugify, and slice filters to generate a new list with only one member.
The following example creates a new list whose sole member is the previous member of the forloop:
{% for item in list %}
{% if not forloop.first %}
{% with forloop.counter0|add:"-1" as previous %}
{% with previous|slugify|add:":"|add:previous as subset %}
{% with list|slice:subset as sublist %}
<p>Current item: {{ item }}</p>
<p>Previous item: {{ sublist.0 }}</p>
{% endwith %}
{% endwith %}
{% endwith %}
{% endif %}
{% endfor %}
This isn't an elegant solution, but the django template system has two faults that make this hack unavoidable for those who don't what to write custom tags:
Django template syntax does not allow nested curly parenthesis. Otherwise, we could do this:
{{ list.{{ forloop.counter|add:-1 }} }}
The lookup operator does not accept values stored using with (and perhaps for good reason)
{% with forloop.counter|add:-1 as index %}
{{ list.index }}
{% endwith %}
This code should work just fine as a django template, as long as object has a property or no-argument method called before, and objects is iterable (and '<' is defined).
{% for object in objects %}
{% if object.before < object %}
this is bigger
{% else %}
this is smaller
{% endfor %}
Maybe it's a little bit stupid question, but I didn't find an answer. Is there any way to use increased/decreased variables in django templates?
e.g.{{ some_variable + 1 }}
There's a built-in add filter:
{{ some_variable|add:"1" }}
One way of doing this is by using a django template filter.
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-filters
def inc(value):
return value+1
and then:
{{ some_variable|inc }}
Inside for loop use forloop.counter that will automatically increase the counter till the records.
{% for a in object_list %}
{{ forloop.counter }}
{% endfor %}
I don't really know how to describe what I'm aiming at (EDIT: I want a dynamic attribute lookup), but I'm trying to do something like this
<p>{{dict.{{object.field}}}}</p> in a template. I also tried:
{% with object.field as field %}
{{dict.field}}
{% endwith %}
which didn't work either. Do you know how to tackle this properly?
See this SO question.
To loop through a dictionary you use "for":
{% for dictionary.object as obj %}
{{ obj.field }}
{% endfor %}