How to display a list of objects containing many-to-many relations in Django template?
I have the following models:
class Tag(models.Model):
name = models.CharField(max_length=20)
class Entry(models.Model):
title = models.CharField(max_length=100)
date = models.DateField()
tags = models.ManyToManyField(Tag)
In a view I create a list of Entry object and want to show the elements in the template:
{% for entry开发者_JAVA百科 in entries %}
{{ entry.title }}
{{ entry.date }}
<!-- {% for tag in entry.tags %} {{ tag }} {% endfor %} -->
{% endfor %}
And with this template code it generates the following TemplateSyntaxError pointing to the template's first line (for tag):
Caught TypeError while rendering: 'ManyRelatedManager' object is not iterable
The entries variable is a list:
entries = Entry.objects.filter(user=user_id)
entries = list(entries)
entries.sort(key=lambda x: x.id, reverse=False)
Do you know what can be the problem here and how to resolve this issue?
I'm new to Django, so any suggestions how to debug the templates may be helpful.
Update
I get the same error even with this template:
{% for entry in entries.all %}
<!-- everything is commented out here -->
{% endfor %}
There is no need to turn the entries QuerySet into a list. Additionally, you can let the DB do the sorting using order_by.
entries = Entry.objects.filter(user_id=user_id).order_by('id')
Add .all
to get all the values from a relationship (just like Entry.objects.all()
).
entry.tags.all
You can try this in the shell as well (I use ipython so your output may look different):
$ ./manage.py shell
# ...
In [1]: from yourproject.models import Entry, Tags
In [2]: entry = Entry.objects.all()[0]
In [3]: entry.tags
Out[3]: <django.db.models.fields.related.ManyRelatedManager object at 0x...>
In [4]: entry.tags.all() # for an entry with no tags.
Out[4]: []
In [5]: # add a few tags
In [6]: for n in ('bodywork', 'happy', 'muscles'):
...: t, created = Tag.objects.get_or_create(name=n)
...: entry.tags.add(t)
In [7]: entry.tags.all()
Out[7]: [<Tag: ...>, <Tag: ...>, <Tag: ...>]
And if you want to call out the entries with zero tags use for..empty.
{% for tag in entry.tags.all %}
{{ tag.name }}
{% empty %}
No tags!
{% endfor %}
Here is the solution of your query,
Verifying your solution by giving an example
Suppose a book have number of tags, so in order to display all the tags of a book on template can be like this
{% for tag in book.tags.all %}
{{ tag.name }}
{% endfor %}
where the model of Tag is like,
class Tag(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return "%s" % unicode(self.name)
OK. I found the problem. I had some incorrect code which was commented out. But Django processed that code. So html comments didn't work here. I fixed this and it all worked like a charm.
So if you didn't know - the html comments don't prevent template processing.
This is because the template is being processed by Django first then HTML is rendered by browser.
The above from istruble is correct but if your question contains all of your code you need to specify a property in your template:
{% for entry in entries %}
{{ entry.title }}
{{ entry.date }}
{% for tag in entry.tags.all %} {{ tag.name }} {% endfor %}
{% endfor %}
or a default unicode function to your model:
class Tag(models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
精彩评论