Django: обход нескольких последовательных отношений ManyToMany в шаблонах за один цикл - PullRequest
2 голосов
/ 14 марта 2011

У меня такая ситуация: есть три модели Django, назовем их article, section и tag, и одна сквозная модель.

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

Затем, в подробном шаблоне раздела, я хочуперечислить все теги из связанных статей.Чтобы сделать это, я сначала должен пройти через отношение ManyToMany Section-Article в обратном порядке (используя related_name), а затем пройти через отношение ManyToMany Article-Tag.Я попробовал это:

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

, но по какой-то причине это не сработало.{% для тега в 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, или мне нужно поместить его в код представления?Если это так, что будет самым чистым способом сделать это там, чтобы я мог избежать дублирования тегов в списке?

1 Ответ

4 голосов
/ 14 марта 2011

Фильтр, который вы ищете, в основном:

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 %}
...