如果我有这样的模型:
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
class PersonSession(models.Model):
start_time = models.DateTimeField(auto_now_add=True)
end_time = models.DateTimeField(null=True,
blank=True)
person = models.ForeignKey(Person, related_name='sessions')
class Billing(models.Model):
DEBT = 'DE'
BALANCED = 'BA'
CREDIT = 'CR'
session = models.OneToOneField(PersonSession,
blank=False,
null=False,
related_name='billing')
STATUS = ((BALANCED, 'Balanced'),
(DEBT, 'Debt'),
(CREDIT, 'Credit'))
status = models.CharField(max_length=2,
choices=STATUS,
blank=False,
default=BALANCED
)
以下两个查询生成不同的结果:
Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \
Q(sessions__start_time__lte='2000-03-01') & \
Q(sessions__billing__status=Billing.DEBT))
OR
Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \
Q(sessions__start_time__lte='2000-03-01')).filter(
Q(sessions__billing__status=Billing.DEBT))
第一个产生两个人1,2而第二个产生我拥有的所有三个人,数据如下:
id | first_name | last_name | id | start_time | end_time | person_id | id | status | session_id
---+------------+-----------+----+---------------------------+---------------------------+-----------+----+--------+------------
0 | person | 0 | 0 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 0 | 0 | DE | 0
0 | person | 0 | 1 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 0 | 1 | BA | 1
0 | person | 0 | 2 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 0 | 2 | DE | 2
1 | person | 1 | 3 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 1 | 3 | BA | 3
1 | person | 1 | 4 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 1 | 4 | DE | 4
1 | person | 1 | 5 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 1 | 5 | DE | 5
2 | person | 2 | 6 | 2000-01-01 16:32:00+03:30 | 2000-01-01 17:32:00+03:30 | 2 | 6 | DE | 6
2 | person | 2 | 7 | 2000-02-01 16:32:00+03:30 | 2000-02-01 17:32:00+03:30 | 2 | 7 | DE | 7
2 | person | 2 | 8 | 2000-03-01 16:32:00+03:30 | 2000-03-01 17:32:00+03:30 | 2 | 8 | BA | 8
我写了一个example,为他们创建类和数据以显示差异。
请解释这两个查询之间有什么区别,作为一个附带问题,如果在django-filter包中我想定义一些字段作为第一个过滤器,我怎么能这样做?
答案 0 :(得分:1)
过滤器生成的查询不同,如下所示:
>>> print Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \
... Q(sessions__start_time__lte='2000-03-01')).filter(
... Q(sessions__billing__status=Billing.DEBT)).query
SELECT "test_filter_person"."id", "test_filter_person"."first_name", "test_filter_person"."last_name" FROM "test_filter_person" INNER JOIN "test_filter_personsession" ON ("test_filter_person"."id" = "test_filter_personsession"."person_id") INNER JOIN "test_filter_personsession" T3 ON ("test_filter_person"."id" = T3."person_id") INNER JOIN "test_filter_billing" ON (T3."id" = "test_filter_billing"."session_id") WHERE ("test_filter_personsession"."start_time" >= 2000-02-01 00:00:00+00:00 AND "test_filter_personsession"."start_time" <= 2000-03-01 00:00:00+00:00 AND "test_filter_billing"."status" = DE)
>>> print Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \
... Q(sessions__start_time__lte='2000-03-01') & \
... Q(sessions__billing__status=Billing.DEBT)).query
SELECT "test_filter_person"."id", "test_filter_person"."first_name", "test_filter_person"."last_name" FROM "test_filter_person" INNER JOIN "test_filter_personsession" ON ("test_filter_person"."id" = "test_filter_personsession"."person_id") INNER JOIN "test_filter_billing" ON ("test_filter_personsession"."id" = "test_filter_billing"."session_id") WHERE ("test_filter_personsession"."start_time" >= 2000-02-01 00:00:00+00:00 AND "test_filter_personsession"."start_time" <= 2000-03-01 00:00:00+00:00 AND "test_filter_billing"."status" = DE)
让我们分别称它们为Q1和Q2。
如您所见,Q1会在Person
,PersonSession
和Billing
之间进行一次联接,并且所有条件都会在WHERE
子句中一起应用。< / p>
但是,在Q2中,由于您使用前两个检查终止了第一个过滤器,因此首先在Person
和PersonSession
之间进行第一次查询连接(对于Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & Q(sessions__start_time__lte='2000-03-01'))
,结果第一次加入再次与PersonSession
和Billing
合并,以便执行过滤查询.filter(Q(sessions__billing__status=Billing.DEBT))
的第二部分。
您可以在此处阅读更多内容:difference between filter with multiple arguments and chain filter in django
还想提请你注意帖子的最后一行:
一个表格:但是如果查询不涉及连接表,例如Yuji和DTing的示例。结果是一样的。