【问题标题】:How to restrict query of a ManyToMany relationship with Q.AND in Django如何在 Django 中使用 Q.AND 限制多对多关系的查询
【发布时间】:2011-06-21 02:17:05
【问题描述】:

我想获取所有具有 2 个特定标签的图像,“tag1”AND“tag2”。我的简化模型:

class Image(models.Model):
    title = models.CharField(max_length=100)

class Tag(models.Model):
    name = models.CharField(max_length=64, unique=True)
    images = models.ManyToManyField(Image, null=True, blank=True)

连接filter 有效:

query = Image.objects.filter(tag__name='tag1').filter(tag__name='tag2')

但是,我认为我可以使用 Django 中的 Q 对象来做到这一点。我正在构建一个复杂的查询,所以使用 Q 会更直接。我正在使用qobj.add(Q(tag__name='tag1'), Q.AND) 将所有参数添加到qobj = Q()。但是...以下内容没有检索到:

qobj = Q()
qobj.add(Q(tag__name='tag1'), Q.AND)
qobj.add(Q(tag__name='tag2'), Q.AND)
query = Image.objects.filter(qobj)

在上面的代码中使用 OR 连接器时,一切都按预期工作,正确返回具有 tag1 OR tag2 的图像。

似乎在AND 的情况下,它正在 app_tag_images 中寻找带有两个标签的行,这显然不存在,因为每一行只有一个 tag_id 用于 image_id。

有没有办法用 Q 构建这个查询?

ps:如果需要更多代码细节,请告诉我。

编辑:

这是带有 Q 的查询的 que sql 查询(为清楚起见,我清理了大多数 SELECT 列):

SELECT "meta_image"."id", "meta_image"."title"
FROM "meta_image"
INNER JOIN "meta_tag_images" ON ("meta_image"."id" = "meta_tag_images"."image_id")
INNER JOIN "meta_tag" ON ("meta_tag_images"."tag_id" = "meta_tag"."id")
WHERE ("meta_tag"."name" = tag1 AND "meta_tag"."name" = tag2)

OR 查询与上述相同(将AND 替换为OR)。

仅供参考,使用过滤器连接的工作方法打印此查询(也简化了):

SELECT "meta_image"."id", "meta_image"."title"
FROM "meta_image"
INNER JOIN "meta_tag_images" ON ("meta_image"."id" = "meta_tag_images"."image_id")
INNER JOIN "meta_tag" ON ("meta_tag_images"."tag_id" = "meta_tag"."id")
INNER JOIN "meta_tag_images" T4 ON ("meta_image"."id" = T4."image_id")
INNER JOIN "meta_tag" T5 ON (T4."tag_id" = T5."id")
WHERE ("meta_tag"."name" = tag1 AND T5."name" = tag2)

【问题讨论】:

  • 这是您自己的标签实现,还是您使用的是 tagging 或 taggit 之类的库?
  • 这是我自己的标签模型,没有外部应用程序。
  • FWIW - 10 年后,也遇到了这个问题。链接 Q() &= Q() for manytomany... 让它工作的唯一方法是链接 .filter()。

标签: python django django-queryset


【解决方案1】:

我什至不知道这种格式!

文档显示 Q 对象使用的方式有什么问题? http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects

Image.objects.filter(Q(tag__name='tag1') & Q(tag__name='tag2'))

更新
我用 m2m 在我的模型上测试了 qobj.add() 方法,它在 1.2.3 上运行良好

它还可以很好地复制和粘贴您的简化模型。

你确定你的查询应该返回一些东西吗?

标准 Q 用法Q(tag__name='tag1') & Q(tag__name='tag2') 是否返回结果?

你也可以打印myquery.query吗?

让我们缩小范围。

【讨论】:

  • 嘿,不,上面的标准方式不返回结果。我设法获得正确结果的唯一方法是连接过滤器。标准格式和 qobj 方法的打印查询是相同的(都不同于 filter concat 方式)。我将编辑帖子并粘贴查询。
猜你喜欢
  • 2013-11-22
  • 2011-11-13
  • 2017-02-02
  • 1970-01-01
  • 2013-07-15
  • 2021-03-07
  • 1970-01-01
  • 2015-10-26
相关资源
最近更新 更多