【问题标题】:How to display a list of objects containing many-to-many relations in Django template?如何在 Django 模板中显示包含多对多关系的对象列表?
【发布时间】:2010-10-22 15:45:43
【问题描述】:

我有以下型号:

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)

在视图中,我创建了一个 Entry 对象列表并希望在模板中显示元素:

   {% for entry in entries %}
     {{ entry.title }}
     {{ entry.date }}
   <!--  {% for tag in entry.tags %} {{ tag }} {% endfor %} -->
   {% endfor %}

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

渲染时捕获 TypeError:'ManyRelatedManager' 对象不可迭代

entrys 变量是一个列表:

entries = Entry.objects.filter(user=user_id)
entries = list(entries)
entries.sort(key=lambda x: x.id, reverse=False)

你知道这可能是什么问题以及如何解决这个问题吗?

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

更新

即使使用此模板,我也会遇到同样的错误:

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

【问题讨论】:

  • 为什么要将“条目”转换为列表并在 Python 中对其进行排序?这是非常低效的。您应该使用 'order_by' 让数据库进行排序。

标签: django django-templates


【解决方案1】:

好的。我发现了问题。我有一些不正确的代码被注释掉了。但是 Django 处理了该代码。所以 html cmets 在这里不起作用。我解决了这个问题,这一切都像一个魅力。

如果您不知道 - html cmets 不会阻止模板处理

这是因为模板首先被 Django 处理,然后 HTML 被浏览器渲染。

【讨论】:

【解决方案2】:

这是您的查询的解决方案,

通过举例验证您的解决方案

假设一本书有多个标签,那么为了在模板上显示一本书的所有标签可以这样

{% for tag in book.tags.all %}
  {{ tag.name }}
{% endfor %}

Tag的模型在哪里,

class Tag(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
    return "%s" % unicode(self.name)

【讨论】:

    【解决方案3】:

    无需将条目 QuerySet 转换为列表。此外,您可以让数据库使用order_by 进行排序。

    entries = Entry.objects.filter(user_id=user_id).order_by('id')
    

    添加.all 以获取关系中的所有值(就像Entry.objects.all())。

    entry.tags.all
    

    您也可以在 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: ...>]
    

    如果你想调出带有零标签的条目,请使用for..empty

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

    【讨论】:

    • 其实我已经尝试添加.all。但在模板方面我得到一个空列表。
    • 更新了 shell 代码以确保至少一个条目有标签。添加了一个使用 for..empty 的模板示例,以显示一种指示没有标签的方法。
    • 问题是它在 shell 中工作。但是在模板中我什么也没得到,尽管整个包含元素。
    • 如果你还在做你的 list(...) 东西,那么请确保你没有在模板中添加 .all。另外,尝试将您的视图代码添加到问题中。或者也许只是在视图中添加import pdb; pdb.set_trace() 并查看您拥有的变量。或者,您可以尝试使用 django-debug-toolbar github.com/robhudson/django-debug-toolbar 查看变量
    • 最好的主意,拯救我的一天。
    【解决方案4】:

    以上来自 istruble 的内容是正确的,但如果您的问题包含所有代码,则需要在模板中指定一个属性:

       {% for entry in entries %}
         {{ entry.title }}
         {{ entry.date }}
         {% for tag in entry.tags.all %} {{ tag.name }} {% endfor %}
       {% endfor %}
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-29
      • 2021-08-28
      • 2015-06-21
      • 1970-01-01
      • 2021-11-13
      • 2011-02-25
      • 1970-01-01
      • 2015-11-16
      相关资源
      最近更新 更多