代码之家  ›  专栏  ›  技术社区  ›  grigy

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

  •  10
  • grigy  · 技术社区  · 14 年前

    我有以下型号:

    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)
    

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

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

    使用此模板代码,它生成以下模板syntaxError,指向模板的第一行(for tag):

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

    entries变量是一个列表:

    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 %}
    
    4 回复  |  直到 12 年前
        1
  •  41
  •   istruble kalyan    14 年前

    不需要将查询集的条目转换为列表。此外,您可以使用 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 %}
    
        2
  •  7
  •   Anupam Shakya    12 年前

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

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

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

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

    标签的模型是这样的,

    class Tag(models.Model):
        name = models.CharField(max_length=100)
    
        def __unicode__(self):
        return "%s" % unicode(self.name)
    
        3
  •  4
  •   grigy    14 年前

    好啊。我发现了问题。我有一些错误的代码被注释掉了。但是Django处理了这个代码。所以HTML注释在这里不起作用。我修好了这个,一切都很有魅力。

    所以如果你不知道- HTML注释不会阻止模板处理

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

        4
  •  3
  •   sunn0    14 年前

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

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