在Django中查询ManyToMany会给我重复的结果

时间:2017-03-22 15:53:32

标签: python django python-2.7 django-1.9

我有两个型号

heat

我试图过滤掉带有标签列表的帖子。让我们说标签warm['heat', 'warm']。我将在我的api函数(PercentRelativeLayout)中获得一个标签列表。我想过滤所有包含其键位于列表中的标签的Post数据。我尝试了很多类型,并没有得到正确的输出。有没有办法在单个查询上执行此操作?

2 个答案:

答案 0 :(得分:2)

此标记键的所有帖子等于heatwarm

Post.objects.filter(tags__key_in=['heat', 'warm']) 

添加distinct以避免重复:

Post.objects.filter(tags__key_in=['heat', 'warm']).distinct()

答案 1 :(得分:0)

尽管Wilfried's answer是正确的并且在许多用例中都很好,但是值得注意的是,在SQL级别,DISTINCT可能会对性能产生影响,尤其是如果您希望查询匹配数据的很大一部分(取决于数据库和表的大小;有关更多详细信息,请参见例如herehere)。

另一个避免这种陷阱的冗长选项是使用through模型和Subquery(在Django 1.11中引入)。基于OP代码:

class Tag(models.Model):
    key = models.CharField(max_length=200)

class Post(models.Model):
    name = models.CharField(max_length=200)
    tags = models.ManyToManyField(Tag, through='Tagging')

class Tagging(models.Model):
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)

以及相应的查询:

tags = Tagging.objects.filter(tag__key__in=['heat', 'warm'])
Post.objects.filter(pk__in=models.Subquery(tags.values('post__pk')))

使用.explain(analyze=True)(在django 2.1中引入)将帮助您做出明智的决定。