Django access array with forloop.counter in template - django

I have an array ['one', 'two', 'three']
In my django template i want to access to elements of the array like that:
{% for a in array %}
{{ array.loop.counter}}
{% endif %}
But array.loop.counter return nothing.
There is a way to access the element of the array based on the loop counter of my for ?

Ok I find a way to do it.
create a template tag into templatetags repository.
Use this custom filter:
from django import template
register = template.Library()
#register.filter(name='index')
def index(sequence, position):
return sequence[position]
Then into the template :
{{ array|index:forloop.counter }}

Why not just do this?:
{% for a in array %}
{{ a }}
{% endif %}

Related

Access tuple through index value in django template

How do I access the value of tuple through indexing in a template? When i try to do this....django gives me the error : Could not parse the remainder: '[0]' from 'tuple[0]'.
template.html:
{{ tuple[0] }}
views.py:
def fun(request):
tuple=('a','b','c','d')
return render(request,'template.html',{'tuple':tuple})
Simply access tuple as in code below:
{{ tuple.0 }}
Also consider using django built-in template tags to iterate over your data, see simple usage below:
{% for item in tuple %}
<span>
{{ item }}
</spam>
{% endfor %}

Django dynamic template variable inside if clause

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

Accessing initial value of django forms when iterating over the fields

I'm trying to do something pretty simple; I'd like to apply a "hidden" style to a form field inside a django template when I've passed in some initial value like this:
form = form_class(initial={'field':data})
Normally, it would be like this:
<li class="{{form.somefield.name}} {% if form.somefield.initial %} hidden{% endif %}>
...
</li>
But I'm iterating over the forms, so what I want do do is something that looks like this:
{% for field in form %}
<li class="{{field.name}} {% if field.initial %} hidden{% endif %}">
...
</li>
{% endfor %}
but this doesn't work, because field.initial only has the value defined as initial to the field in the form, not the data that's passed in at the form's creation. Is there a good solution for this besides just breaking out the iterating into individual forms?
Some (bad) solutions I've thought of:
overriding init to stuff values form self.initial into self.fields;
writing a template tags called {% hideifhasinitial %}
adding a method to the form that uses zip on self and self.initial (doesn't work, since self.initial only had one element and self had 4, it only iterated over 1 element, and the keys (field names) didn't match up).
how about this?
{% for field in form %}
{% if field.name in field.form.initial.keys %}
...
{% endif %}
{% endfor %}
Initial data can be accessed on the value attribute, initial data represents the value of the field:
{{field.value}}
Turns out there's a way easier way to do this.
{% if field.name in form.initial.keys %}
The solution with the initial keys has not worked for me, because the field contains as a value an empty string. I had to write my own custom tag:
from django import template
register = template.Library()
#register.simple_tag
def field_empty(field):
if not field.form.initial.get(field.name):
return ' hidden'
return ''
In your example, I would use the tag this way:
<li class="{{ field.name }} {% field_empty field %}">

Django templates: value of dictionary key with a space in it

In a Django template, is there a way to get a value from a key that has a space in it?
Eg, if I have a dict like:
{"Restaurant Name": Foo}
How can I reference that value in my template? Pseudo-syntax might be:
{{ entry['Restaurant Name'] }}
There is no clean way to do this with the built-in tags. Trying to do something like:
{{ a.'Restaurant Name'}} or {{ a.Restaurant Name }}
will throw a parse error.
You could do a for loop through the dictionary (but it's ugly/inefficient):
{% for k, v in your_dict_passed_into_context %}
{% ifequal k "Restaurant Name" %}
{{ v }}
{% endifequal %}
{% endfor %}
A custom tag would probably be cleaner:
from django import template
register = template.Library()
#register.simple_tag
def dictKeyLookup(the_dict, key):
# Try to fetch from the dict, and if it's not found return an empty string.
return the_dict.get(key, '')
and use it in the template like so:
{% dictKeyLookup your_dict_passed_into_context "Restaurant Name" %}
Or maybe try to restructure your dict to have "easier to work with" keys.
You can use a custom filter as well.
from django import template
register = template.Library()
#register.filter
def get(mapping, key):
return mapping.get(key, '')
and within the template
{{ entry|get:"Restaurant Name" }}

Django templates: loop through and print all available properties of an object?

I have a database object called manor_stats, with around 30 fields. For most rows, most of these fields will be null.
In my template, I'd like to loop through all the fields in the row, and print info for only the fields that aren't null.
For example, there's a field called "name": I'd like to print <li>Name: {{ manor_stats.name }}</li> in the template ONLY for those objects where the field isn't null. Ideally I'd like to pull in "Name: " from somewhere automatically too, rather than specifying it.
I know I could use {% if manor_stats.name %} to check whether each field is null, but I don't want to do that 30 times for all the fields.
Here's what I have in views.py:
manor_stats = Manors.objects.get(idx=id)
return render_to_response('place.html', { 'place' : place, 'manor_stats' : manor_stats }, context_instance = RequestContext(request))
And then in place.html, I'd like to have something that works approximately like this (pseudocode, with ??? indicating the bits that I don't know how to do):
{% if manor_stats %}
<ul>
{% for manor_stats.property??? in manor_stats %}
{% if manor_stats.property %}
<li>{{ manor_stats.property.field_name??? }} {{ manor_stats.property.value??? }}</li>
{% endif %}
{% endfor %
{% endif %}
Hope that makes sense...
You could add a method to your Manors model that will return all the field values, from there you can just loop over these values in your template checking to see if the value isn't null.
-- models.py
class Manors(models.Model)
#field declarations
def get_fields(self):
return [(field.name, field.value_to_string(self)) for field in Manors._meta.fields]
-- manor_detail.html
{% for name, value in manor_stats.get_fields %}
{% if value %}
{{ name }} => {{ value }}
{% endif %}
{% endfor %}
The following approach only requires defining a single custom template filter (see the docs) - it's DRY'er than having to write or copy a method into every model you need this functionality for.
-- my_app/templatetags/my_tags.py
from django import template
register = template.Library()
#register.filter
def get_fields(obj):
return [(field.name, field.value_to_string(obj)) for field in obj._meta.fields]
You'll need to restart your server to get the new tags registered and available in your templates.
-- my_app/templates/my_app/my_template.html
{% load my_tags %}
<ul>
{% for key, val in object|get_fields %}
<li>{{ key }}: {{ val }}</li>
{% endfor %}
</ul>
Tested in Django 1.11.
NB: Since ._meta is a private attribute it's functionality might well change in the future.
Thanks to the other answers on this post that took me most of the way, particularly W. Perrin.
Use Model._meta.get_fields() in python code.
>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
....
In template, we can define a filter to retrieve all the fields.
├─my_app
│ │
│ ├─templatetags
│ │ │ my_filters.py
│ │
from django import template
register = template.Library()
#register.filter
def get_fields(obj):
return obj._meta.get_fields()
{% for k,v in obj|get_fields %}
<td> {{k}} </td>
{% endfor %}
See this link: https://docs.djangoproject.com/en/2.0/ref/models/meta/#retrieving-all-field-instances-of-a-model