高效查询Django查询集与不同模型的交集

时间:2016-03-29 03:44:29

标签: django

我正在尝试稍微复杂的Django查询集交互,我遇到了障碍。

class A(models.Model):
    owner = models.ForeignKey(User)
    x = models.CharField(max_length=10)
    y = models.CharField(max_length=10)

class B(models.Model):
    owner = models.ForeignKey(User)
    x = models.CharField(max_length=10)
    y = models.CharField(max_length=10)

a_queryset = user.a_set.filter(x__in=("foo", "bar", "baz"))
b_queryset = B.objects.filter(???)

有人碰巧知道生成具有与给定A查询集相同的x / y对的B对象的查询集的有效方法吗?给定一个任意的a_queryset,有没有快速的方法呢?

2 个答案:

答案 0 :(得分:0)

您无法使用queryset执行此操作,因为AB即使它们具有间接关系(user模型),您也不会查询它,因此之间没有关系他们。

你可以使用python内置函数来完成它。

答案 1 :(得分:0)

根据a_queryset,您可以获得(x, y)对并使用Q objects构建查询

首先,从(x, y)获取a_queryset个唯一对:

xy_pairs = a_queryset.values_list('x', 'y').distinct()
# [('x1', 'y1'), ('x2', 'y2'), ('x1', 'y2'), ('x2', 'y1')]

对于('x1', 'y1')对,您可以轻松搜索所有B个对象,如下所示:

b_objs = B.objects.filter(x='x1', y='y1')

但是,在这里你需要构建一个如下所示的查询:

# (x='x1' AND y='y1') OR (x='x2' AND y='y2') .... etc.

您可以通过创建Q objects

来实现这一目标
# first create AND queries for different (x, y) pairs
q_and_queries = [(Q(x=x) & Q(y=y)) for x, y in xy_pairs]

#[<Q: (AND: ('x', 'x1'), ('y', 'y1'))>,
# <Q: (AND: ('x', 'x2'), ('y', 'y2'))>,
# <Q: (AND: ('x', 'x1'), ('y', 'y2'))>,
# <Q: (AND: ('x', 'x2'), ('y', 'y1'))>]

# then combine those queries using OR
q_or_query = Q()
for q in q_and_queries:
    q_or_query |= q

# <Q: (OR: (AND: ), (AND: ('x', 'x1'), ('y', 'y1')), (AND: ('x', 'x2'), ('y', 'y2')), (AND: ('x', 'x1'), ('y', 'y2')), (AND: ('x', 'x2'), ('y', 'y1')))>

现在,您可以使用最终查询q_or_query从模型B获取所需的查询集:

b_queryset = B.objects.filter(q_or_query)