【问题标题】:Django Queryset using the .extra to query many-to-many relationshipsDjango Queryset 使用 .extra 查询多对多关系
【发布时间】:2014-07-23 17:40:50
【问题描述】:

所以我试图过滤一个大型数据库,发现我需要一个复杂的 WHERE 子句才能真正完成我需要的搜索。不幸的是,我的 SQL 知识非常缺乏,所以我希望有人能指出我想要的正确方向。

所以我已经想出如何做的是以下内容。假设我有一个 Django 模型:

class ExampleModel(models.Model):
    param_a = models.CharField(max_length = 50)
    param_b = models.CharField(max_length = 50)
    param_c = models.CharField(max_length = 50)
    param_d = models.CharField(max_length = 50)

我希望能够搜索所有具有 param_a 等于“A”且 param_b 等于“b”或“B”的 ExampleModel,所以我发现我可以使用 where 搜索:

ExampleModel.objects.extra(where=["param_a='A'", "param_b='b' OR param_b='B'"])

效果很好,正是我想要的。但是假设我添加了另一个项目:

class ManyToManyModel(models.Model):
    name = models.CharField(max_length = 50)

并在 ExampleModel 中添加多对多关系:

class ExampleModel(models.Model):
    param_a = models.CharField(max_length = 50)
    param_b = models.CharField(max_length = 50)
    param_c = models.CharField(max_length = 50)
    param_d = models.CharField(max_length = 50)
    param_e = models.ManyToManyField('ManyToManyModel', related_name = 'manytomanymodel_set')

有没有办法根据这个参数用.extra(where=[]) 方法查询?


更新:

所以我意识到我几乎可以通过 .filter 操作完成我想要的,但我还有另一个问题。

假设我想查找 param_e 具有名称为“A”的 ManyToManyModel 或名称为“B”的 ManyToManyModel 我可以使用的所有 ExampleModel:

ExampleModel.objects.filter(param_e__name__in = ['A', 'B'])

但我现在不知道的一件事是如何找到一个名称为“A”AND“B”的。比如,说 param_e 在 manytomany 字段中有四个 ManyToManyModel,名称分别为“A”、“B”、“C”和“D”。搜索完全匹配很容易,但是找到所有包含“A”和“B”以及其他任何内容的示例模型,是否有过滤器?我似乎在 Django 文档中找不到它。

【问题讨论】:

  • 你为什么使用extra?您作为示例提供的查询可以使用通常的filter 轻松完成。
  • 是的,自从发布这个问题以来,我已经意识到这一点,但现在我遇到了另一个问题——现在更新问题。

标签: python mysql sql django


【解决方案1】:

看这里:https://docs.djangoproject.com/en/1.6/topics/db/queries/#complex-lookups-with-q-objects

在应用于查询集之前,可以使用 OR 或 AND 等逻辑运算来组合这些 Q 对象。

【讨论】:

  • 不幸的是,这不正常。
  • 也许,你可以显示一些代码吗? Q(...name=A) & Q(...name=B) & Q(...name__in[C, D]) 不起作用?
【解决方案2】:

嗯,有可能……

ids = ExampleModel.objects.filter(param_e__name__in = ['A', 'B']).distinct().values_list('id', flat=True)

然后:

from django.db.models import Count
ExampleModel.objects.filter(id__in=ids).annotate(match_count=Count('param_e')).filter(match_count=2)

你问它有什么作用?

  1. 为您的 param_e__name 过滤 ExampleModel
  2. 只获取不同的对象,
  3. 获取对象 ID(以进行另一个查询)
  4. 使用 id 列表过滤,
  5. 用标签项的数量注释对象
  6. 再次过滤,对于计数等于 2 的对象,因为您只指定了两个名称(“A”和“B”)。

我选择先获取 id,因为我在组合过滤和注释时得到了错误的结果,必须检查一下。

【讨论】:

  • 仍然没有正确地做我正在寻找的东西。我已经适应了连续的过滤器
猜你喜欢
  • 2015-10-26
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 2013-07-15
  • 2014-07-14
  • 2021-03-07
  • 2019-05-18
  • 2017-02-02
相关资源
最近更新 更多