Django,仅从相关对象中获取唯一值

时间:2018-10-11 21:12:16

标签: python django

我希望我可以在我的网站上显示最常用标签的列表。问题是显示的标签经常重复显示,我敢肯定,如果只显示唯一标签,效果会更好。

在我的模型中,我编写了方法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,我具有与特定字段相关的所有文章实例。我在视图中使用了明细视图。

所以,我的第一个问题是,这是有效的方法吗?我的意思是,在模型类中添加新方法,还是应该在视图中添加此方法?。我仍然对django模板语言不满意,所以也许有问题。而且我知道模板中有此过滤器,例如{{some_object |函数}},但我已经读到,最好在模板中保留尽可能少的逻辑。

1 个答案:

答案 0 :(得分:2)

如果要执行此操作,我会在Article级别上为 添加逻辑:

class Article(models.Model):

    def unique_tags(self):
        return Tag.objects.filter(articletag__article=self).distinct()

,然后使用以下命令进行查询:

{% for article_tag in prev_article.unique_tags %}
    <li><a href="#">{{article_tag.tag.verbose_name}}</a></li>
{% endfor %}

通过使用.values_list,您将获得主键的 value ,因此通常是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:
        unique_together = ('article', 'tag')

所以现在您不能简单地用相同的标签对同一篇文章进行两次标签。因此,一旦强制实施,您就可以使用:

<!-- given unique_together is enforced -->

{% for article_tag in prev_article.tags.all %}
    <li><a href="#">{{article_tag.tag.verbose_name}}</a></li>
{% endfor %}

然后您可以使用.prefetch_related(..)来以恒定数量的查询加载所有相关对象。