Django Queryset使用.extra查询多对多关系

时间:2014-07-23 17:40:51

标签: python mysql sql django

所以我试图过滤大型数据库,发现我需要一个复杂的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"的所有ExampleModel。或" B"所以我发现我可以使用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操作完成我想要的东西,但我还有另一个问题。

假设我想找到所有的ExampleModel,其中param_e有一个名字为'的A'的ManyToManyModel,或者名为' B'的ManyToManyModel。我可以用:

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

但我现在无法弄清楚的一件事就是如何找到一个名字叫A' AND ' B'。比方说,param_e在manytomany字段中有四个ManyToManyModel,名称为' A' B',' C'和' D' 。搜索完全匹配很容易,但找到包含' A'的所有ExampleModel。和' B'还有别的,那有过滤器吗?我似乎无法在Django文档中找到它。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

嗯,有可能......

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
  2. 的ExampleModel
  3. 只获取不同的对象,
  4. 获取对象ID(进行其他查询)
  5. 使用ID列表进行过滤,
  6. 使用标记项计数注释对象
  7. 再次过滤,对于count等于2的对象,因为你只指定了两个名字('A'和'B')。
  8. 我选择首先获得ID,因为在结合过滤和注释时我得到了错误的结果,必须检查出来。