我希望我可以在我的网站列表中呈现最常用的标签,我确实这样做了。问题是,显示的标签经常重复,我相信如果只显示唯一的标签会好得多。
在我的模型中,我编写了方法 unique_tags
class ArticleTag(models.Model):
article = models.ForeignKey('ep.Article', on_delete=models.CASCADE, related_name='tags')
tag = models.ForeignKey('ep.Tag', on_delete=models.CASCADE)
def unique_tags(self):
return self.objects.values_list('tag').distinct()
当我在 python shell 中测试它时它工作正常。但它不呈现任何标记。我的模板如下所示:
<div class="widget-tags">
<ul>
{% for prev_article in object.articles.all %}
{% for article_tag in prev_article.article.tags.all.unique_tags %}
<li><a href="#">{{article_tag.tag.verbose_name}}</a></li>
{% endfor %}
{% endfor %}
</ul>
</div>
对象来自与 Article 表和 Field 表建立关系的模型,所以使用 object.articles.all 我得到了与特定领域相关的文章的所有实例。我使用 detail在我看来。
那么,我的第一个问题是,这种方法有效吗?我的意思是,在模型类中添加新方法,或者也许我应该在 View 中添加它?而且我仍然对 django 模板语言不满意,所以可能存在问题。而且我知道模板中有这个过滤器,如 {{ some_object | function}} 但我读到,在模板中尽可能少地保留逻辑是一种很好的做法。
请您参考如下方法:
如果您想这样做,我会在 Article 级别添加逻辑::
class Article(models.Model):
def unique_tags(self):
return Tag.objects.filter(articletag__article=self).distinct()
然后查询:
{% for article_tag in <b>prev_article.unique_tags</b> %}
<li><a href="#">{{article_tag.tag.verbose_name}}</a></li>
{% endfor %}
通过使用 .values_list,您将获得主键的值,因此通常是 int(或给定的其他原始类型你自己定义了一个主键)。
话虽如此,我认为最好通过添加 unique_together [Django-doc] 来确保这永远不会发生。模型中的约束:
class ArticleTag(models.Model):
article = models.ForeignKey(
'ep.Article',
on_delete=models.CASCADE,
related_name='tags'
)
tag = models.ForeignKey('ep.Tag', on_delete=models.CASCADE)
class Meta:
<b>unique_together = ('article', 'tag')</b>
因此,现在您可以简单地不为同一篇文章标记两次相同的标签。因此,一旦强制执行,您可以简单地使用:
<!-- given unique_together is enforced -->
{% for article_tag in <b>prev_article.tags.all</b> %}
<li><a href="#">{{article_tag.tag.verbose_name}}</a></li>
{% endfor %}
然后您可以使用 .prefetch_related(..) 加载所有具有恒定数量查询的相关对象。
