如何在Django模板中显示包含多对多关系的对象列表?

时间:2022-08-29 20:22:42

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 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):

使用这个模板代码,它会生成以下模板的第一行(用于标记)的TemplateSyntaxError:

Caught TypeError while rendering: 'ManyRelatedManager' object is not iterable

呈现时捕获的类型错误:“ManyRelatedManager”对象不可迭代

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.

我是Django的新手,所以任何关于如何调试模板的建议都是有帮助的。

Update

更新

I get the same error even with this template:

即使是这个模板,我也会得到同样的错误:

{% for entry in entries.all %}
<!-- everything is commented out here -->
{% endfor %}

4 个解决方案

#1


38  

There is no need to turn the entries QuerySet into a list. Additionally, you can let the DB do the sorting using order_by.

不需要将条目QuerySet转换为列表。此外,还可以让DB使用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()).

Add .all从关系中获取所有值(就像Entry.objects.all()一样)。

entry.tags.all

You can try this in the shell as well (I use ipython so your output may look different):

您也可以在shell中尝试(我使用ipython,这样您的输出看起来可能不同):

$ ./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.

如果你想要调用那些没有标记的条目,则使用..empty。

{% for tag in entry.tags.all %}
    {{ tag.name }}
{% empty %}
    No tags!
{% endfor %}

#2


6  

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)

#3


4  

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.

好的。我发现这个问题。我有一些不正确的代码被注释掉了。但是Django处理了这些代码。html注释在这里不起作用。我把它修好了,一切都像魔法一样。

So if you didn't know - the html comments don't prevent template processing.

如果你不知道- html注释不会阻止模板处理。

This is because the template is being processed by Django first then HTML is rendered by browser.

这是因为模板先由Django处理,然后由浏览器呈现HTML。

#4


3  

The above from istruble is correct but if your question contains all of your code you need to specify a property in your template:

上面的istruble是正确的,但是如果您的问题包含了您需要在模板中指定属性的所有代码:

   {% 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:

或您的模型的默认unicode函数:

class Tag(models.Model):
  name = models.CharField(max_length=20)
  def __unicode__(self):
      return self.name

#1


38  

There is no need to turn the entries QuerySet into a list. Additionally, you can let the DB do the sorting using order_by.

不需要将条目QuerySet转换为列表。此外,还可以让DB使用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()).

Add .all从关系中获取所有值(就像Entry.objects.all()一样)。

entry.tags.all

You can try this in the shell as well (I use ipython so your output may look different):

您也可以在shell中尝试(我使用ipython,这样您的输出看起来可能不同):

$ ./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.

如果你想要调用那些没有标记的条目,则使用..empty。

{% for tag in entry.tags.all %}
    {{ tag.name }}
{% empty %}
    No tags!
{% endfor %}

#2


6  

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)

#3


4  

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.

好的。我发现这个问题。我有一些不正确的代码被注释掉了。但是Django处理了这些代码。html注释在这里不起作用。我把它修好了,一切都像魔法一样。

So if you didn't know - the html comments don't prevent template processing.

如果你不知道- html注释不会阻止模板处理。

This is because the template is being processed by Django first then HTML is rendered by browser.

这是因为模板先由Django处理,然后由浏览器呈现HTML。

#4


3  

The above from istruble is correct but if your question contains all of your code you need to specify a property in your template:

上面的istruble是正确的,但是如果您的问题包含了您需要在模板中指定属性的所有代码:

   {% 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:

或您的模型的默认unicode函数:

class Tag(models.Model):
  name = models.CharField(max_length=20)
  def __unicode__(self):
      return self.name