【问题标题】:Querying ManyToMany in Django giving me duplicate results在Django中查询ManyToMany给我重复的结果
【发布时间】:2017-08-14 20:49:21
【问题描述】:

我有两个模型

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

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

我正在尝试使用标签列表过滤掉帖子。让我们说标签heatwarm。我将在我的 api 函数中获得标签列表 (['heat', 'warm'])。我想过滤所有具有其键在列表中的标签的 Post 数据。我尝试了很多类型,但没有得到正确的输出。有没有办法在单个查询上做到这一点?

【问题讨论】:

  • 你能显示你除了什么输出吗?我不确定你需要什么。

标签: python django python-2.7 django-1.9


【解决方案1】:

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

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

添加 distinct 以避免重复:

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

【讨论】:

    【解决方案2】:

    虽然Wilfried's answer 对很多用例来说是正确的并且非常好,但值得注意的是,在 SQL 级别上,DISTINCT 可能会对性能产生影响,尤其是如果您希望查询匹配您的大部分内容时数据(取决于数据库和表的大小;有关详细信息,请参阅例如 herehere)。

    另一个稍微详细一点的选项可以避免这个陷阱,它使用through 模型和Subquery(在 django 1.11 中引入)。基于 OPs 代码:

    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 中引入)将帮助您做出明智的决定。

    【讨论】:

    • 这样好多了。不同的查询对数据库来说可能是灾难性的。
    猜你喜欢
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 2011-10-18
    • 2023-03-18
    • 2011-05-15
    • 1970-01-01
    • 2015-06-23
    相关资源
    最近更新 更多