很抱歉,如果这个问题听起来很奇怪。我只是想知道当我已经有一个查询集时是否有可能创建新的查询集。
例如这里......
everyone = User.objects.filter(is_active=True) # this would of course return all users that's active
not_deleted = User.objects.filter(is_active=True, is_deleted=False) # return user that's active and not deleted
is_deleted = User.objects.filter(is_active=True, is_deleted=True) # return user that's active and is already deleted
我的问题是......对于not_deleted
和is_deleted
他们都有效,这与everyone
相同是否可以使用everyone
然后以某种方式筛选出is_deleted=True
或is_deleted=False
?那么我相信如果可能的话,查询会更快更好吗?
然后,所有三个变量everyone
,not_deleted
和is_deleted
将被用于其他内容。
希望我能清楚明白我的问题。
提前致谢。
答案 0 :(得分:11)
是的,您可以重用现有的查询集。
everyone = User.objects.filter(is_active=True)
active_not_deleted = everyone.filter(is_deleted=False)
active_is_deleted = everyone.filter(is_deleted=True)
实际上,这并没有真正做得更快,实际上,这个代码块甚至不会对数据库执行查询,因为Django QuerySets被懒惰地评估。我的意思是,在您确实需要值之前,它不会将查询发送到数据库。这是一个与数据库对话的例子。
everyone = User.objects.filter(is_active=True) # Building SQL...
active_not_deleted = everyone.filter(is_deleted=False) # Building SQL...
active_is_deleted = everyone.filter(is_deleted=True) # Building SQL...
# Example of the whole queryset being evaluated
for user in everyone:
# This will execute the query against the database to return the list of users
# i.e. "select * from user where is_active is True;"
print(user)
# Example of using iterator to evaluate one object at a time from the queryset.
for user in active_not_deleted.iterator():
# This will execute the query for each result, so it doesn't
# load everything at once and it doesn't cache the results.
# "select * from user where is_active is True and is_deleted is False limit 1 offset 0;"
# The offset is incremented on each loop and another query is sent to retrieve the next user in the list.
print(user)
推荐阅读:
作为对此答案的补充,您可以进行单个查询,然后根据您的需要在Python中进行过滤。请注意,您无法对列表进行后续过滤,因为它们不是QuerySets。
everyone = User.objects.filter(is_active=True)
active_not_deleted = list(filter(lambda user: user.is_deleted is False), list(everyone))
active_is_deleted = list(filter(lambda user: user.is_deleted is True), list(everyone))
在最后一个示例中,everyone
是一个查询集,active_not_deleted
和active_is_deleted
是用户对象的Python列表。 everyone
查询集仅在第一次list(everyone)
调用中评估一次,然后缓存结果。
答案 1 :(得分:1)
not_deleted = User.objects.filter(active=True).filter(is_deleted=False)
@Cory Madden已经回答了。 User.objects.filter(active=True)
返回Queryset。所以你可以添加过滤方法。 active_users.filter(is_deleted=False)
from django.db.models import Q
not_deleted = User.objects.filter(Q(active=True) & Q(is_deleted=False)
管理复杂的查询集更容易。如果你想过滤userID怎么样不是3?您可以像User.objects.filter(Q(active=True) & ~Q(id = 3))
回答你的意见,
是否使用Q,它具有相同的原始查询。
SELECT ... FROM ...
WHERE ("auth_user"."active" = True AND "auth_user"."is_deleted" = False)
数据库性能与您在数据库中提取数据的频率有关,或者当您通过FK关系提取某些内容时使用重度方法(如“加入”)。所以使用Q或不会给你性能差异,因为它有相同的查询句子。
此外,
user = User.objects.filter(active=True)
not_deleted = User.objects.filter(active=True).filter(is_deleted=False)
user = User.objects.filter(active=True)
not_deleted = user.filter(is_deleted=False)
不会给你性能差异。
Queryset很懒。 user
和not_deleted
个变量只有queryset字符串。当您定义上面的变量时,它不会立即命中数据库。无论如何,你会为每个变量点击三次。
答案 2 :(得分:0)
你能做的最好的事情是:
active_users = User.objects.filter(active=True)
not_deleted = active_users.filter(is_deleted=False)
deleted = active_users.filter(is_deleted=True)
因此,如果我理解正确,你问题的答案可能是肯定的。
答案 3 :(得分:0)
您可以根据需要过滤Queryset,因为filter()
会返回一个新的Queryset,因此在过滤后您将获得过滤后的Queryset,您可以执行过滤或命令以及另一个methods that return new QuerySets
所以你可以这样做:
active = User.objects.filter(active=True)
deleted = active.filter(is_deleted=True)
not_deleted = active.filter(is_deleted=False)
所有这一切都是因为User.objects
- 是Queryset而User.objects.filter
也返回Queryset。