简体   繁体   中英

Django loop and accessing the objects and dictionary items in template

So I came across this problem with django templates and I thought the solution might be useful for others:
here I will assume a pretty complicated situation so it also can be used in simpler cases:
let's assume we need to access a list of articles and their id and title in the template. additionally we want to pass some extra data about each article (like publisher) using a dictionary since they are not in the class attributes. what makes it even harder is when you want to access this articles two by two. meaning a for loop iterating over range of 0 to index of last item and being able to access item number i and i+1 at the same time.
this was particularly hard because as you might know if you want to use a dictionary in django template you can't do:

{{ publishers[article.id] }}

because [] are not supported in the template. no big deal you can treat fields as attributes like

{{ publishers.0 }}

but django template won't let you do

{{ publishers.article.id }}

let alone using a for loop and accessing articles through a list and index like :

{{ publishers.articles.i.id }}

so what do we do???

so here's the answer. it's a bit over complicated but I wanted to cover all the possibilities.
first off we need to be able to access objects of a dictionary by defining our own filter like this :

from django import template
register = template.Library()

def hash_dict(h, key):  
   return h[key]

def get_attr(item,field):
   dict_obj = item.__dict__
      return dict_obj[field]

register.filter('hash_dict',hash_dict)
register.filter('get_attr',get_attr)

we'll get to the get_attr method in a moment but for now, we can access dictionary objects in the template :

{% load modulename %}
{{ dictionary|hash_dict:obj.id }}

to have a for loop with counter you can pass a range object or list to the template.

range_of_article = range(0, len(articles_list), 2)

and somehow pass that variable to the template.
in your template :

{% for i in range_of_article %}
   {% with article=articles|hash_dict:i %}
      {% with article_id=article|get_attr:'id' %}
         {{ publishe|hash_dict:article_id }}

this is where get_attr method comes in handy. I could have just used article.id with no problems here but sometimes that's not the case. I find this workaround to be very useful when you cant access an attrubute of object with object.attribute won't work.
and finally to have access to i and i+1 at the same time:

{% for i in range_of_article %}
   {% with j=i|add:1 %}
      {% with article=articles|hash_dict:i article2=articles|hash_dict:j %}
         {% with article_id=article|get_attr:'id'  article_id2=article2|get_attr:'id'%}
            {{ publishe|hash_dict:article_id }}
            {{ publishe|hash_dict:article_id2 }} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM