Django ORM Queryset class 使用相同的过滤器表现不同

Django ORM Queryset class behave different with same filters

这是一个简单的问题。

我想使用 Queryset 一次过滤 2 个过滤器 class。让我解释。

from django.db.models import Q
import datetime
from .models import Asset

query_set = Asset.objects.filter(category__name="car")

date_query = {'eav__date__gte': datetime.datetime(2018, 9, 2, 0, 0), 'eav__date__lte': datetime.datetime(2018, 9, 14, 0, 0)}

number_query = {'eav__price__gte': '60', 'eav__price__lte': '600'}

total_query = {'eav__date__gte': datetime.datetime(2018, 9, 2, 0, 0), 'eav__date__lte': datetime.datetime(2018, 9, 14, 0, 0),'eav__price__gte': '60', 'eav__price__lte': '600'}

query_set = query_set.filter(Q(**number_query))

query_set = query_set.filter(Q(**date_query))

在这种情况下,query_set 不是空的!


query_set = query_set.filter(Q(**total_query))

在这种情况下,query_set是空的!


有人可以解释一下这两个查询之间的区别吗?提前致谢。

这是因为您正在过滤多值关系。正如 the docs 解释:

Django has a consistent way of processing filter() calls. Everything inside a single filter() call is applied simultaneously to filter out items matching all those requirements. Successive filter() calls further restrict the set of objects, but for multi-valued relations, they apply to any object linked to the primary model, not necessarily those objects that were selected by an earlier filter() call.

因此,您的第一个案例选择了所有具有符合日期要求的 EAV 和符合价格要求的 EAV 的资产,但 不一定是相同的 EAV。您的第二种情况仅选择那些具有同时满足 both 要求的 EAV 的资产。

使用Q对象构建查询集。 在 Django 中处理查询的最简单方法 在你的情况下

query_set = query_set.filter(Q(**number_query))
query_set = query_set.filter(Q(**date_query))

这些是不同的查询集。

query_set = query_set.filter(Q(**total_query))

在这里,您合并了两个没有 AND 、OR 条件的查询,因此它是空的。 在这里你想要和条件我想所以用这个 Q(first_name__startswith='R') & Q(last_name__startswith='D')