2011-03-14 107 views
2

我有这样的情况:有三个Django模型,我们称它们为article,section和tag,以及一个through-model。Django:在一个循环中遍历模板中的多个连续ManyToMany关系

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

class Section(models.Model): 
    # all sorts of fields here 

class Article(models.Model): 
    tags = models.ManyToManyField(Tag, null=True, blank=True) 
    sections = models.ManyToManyField(Section, null=True, blank=True, through='SectionInArticle', related_name='articles') 

class SectionInArticle(models.Model): 
    article = models.ForeignKey(Article) 
    section = models.ForeignKey(Section) 
    order = models.IntegerField() 

然后,在该部分的详细模板中,我想列出相关文章中的所有标签。要做到这一点,我首先必须反过来(使用related_name)遍历Section-Article ManyToMany关系,然后遍历Article-Tag ManyToMany关系。我试过这个:

{# doesn't print anything: #} 
{% for tag in object.articles.tags.all %} 
{{ tag.name }} 
{% endfor %} 

但由于某些原因,这并没有奏效。 {%for object in object.articles.all.tags.all%}也没有工作。我可以使用嵌套循环打印所有标签,但这意味着重复成为一个问题。

{# duplicates are an issue here: #} 
{% for article in object.articles.all %} 
    {% for tag in article.tags.all %} 
    {{ tag.name }} 
    {% endfor %} 
{% endfor %} 

在Django模板中有没有一种简洁的方式来做到这一点,还是我必须把它放在视图代码中?如果是这样,在那里做最干净的方法是什么,这样我可以避免列表中的重复标签?

回答

4

你正在寻找的过滤器基本上是:

Tag.objects.filter(article__sections=section) 

你可以把它放在你的看法,或者你可以为它添加到您的第模型属性:

class Section(models.Model): 
# all sorts of fields here 
@property 
def tags(self): 
    return Tag.objects.filter(article__sections=self).all() 

而且然后在模板中做:

{% for tag in object.tags %} 
    {{ tag.name }} 
{% endfor %} 
+0

谢谢!这似乎是诀窍,而且非常优雅。 – 2011-03-14 14:39:23

+0

好戏。谢谢! – Gnijuohz 2012-09-23 04:38:43