开发者

How to display a list of objects containing many-to-many relations in Django template?

开发者 https://www.devze.com 2023-01-20 19:15 出处:网络
I have the following models: class Tag(models.Model): name = models.CharField(max_length=20) class Entry(models.Model):

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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号