Python 可以在查询后过滤查询集吗?姜戈
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45228187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
possible to filter the queryset after querying? django
提问by Dora
Sorry if the question sounds weird. I am just wondering if there is possible to make new queryset when I already have a queryset.
对不起,如果问题听起来很奇怪。我只是想知道当我已经有一个查询集时是否可以创建新的查询集。
For example here...
例如这里...
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
What my question is...for not_deleted
and is_deleted
they both have active is true with is the same as everyone
is there a possible way to use everyone
and then somehow filter out is_deleted=True
or is_deleted=False
? So then I believe the querying would be faster and better if this is possible right?
我的问题是什么?对于not_deleted
和is_deleted
他们都有积极作为是相同真正everyone
有使用一个可能的方式everyone
,然后以某种方式过滤掉is_deleted=True
或is_deleted=False
?那么我相信如果这是可能的,查询会更快更好吗?
All three variables everyone
, not_deleted
and is_deleted
will then be used for something else.
所有这三个变量everyone
,not_deleted
并且is_deleted
将被用于别的东西。
Hopefully I made my question quiet clear.
希望我把我的问题说清楚了。
Thanks in advance.
提前致谢。
回答by A. J. Parr
Yes, you can reuse existing querysets.
是的,您可以重用现有的查询集。
everyone = User.objects.filter(is_active=True)
active_not_deleted = everyone.filter(is_deleted=False)
active_is_deleted = everyone.filter(is_deleted=True)
This is not really making anything faster though, in fact, this code block won't even execute a query against the database because Django QuerySets are lazily evaluated. What I means is that it won't send the query to the database until you actually need the values. Here's an example that will talk to the database.
虽然这并没有真正使任何事情变得更快,但事实上,这个代码块甚至不会对数据库执行查询,因为 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)
Recommend reading:
推荐阅读:
- https://docs.djangoproject.com/en/1.11/topics/db/queries/#querysets-are-lazy
- https://docs.djangoproject.com/en/1.11/ref/models/querysets/#iterator
- https://docs.djangoproject.com/en/1.11/topics/db/queries/#caching-and-querysets
- https://docs.djangoproject.com/en/1.11/topics/db/queries/#querysets-are-lazy
- https://docs.djangoproject.com/en/1.11/ref/models/querysets/#iterator
- https://docs.djangoproject.com/en/1.11/topics/db/queries/#caching-and-querysets
As an addition to this answer, you could make a single query and then filter in Python if you really wanted. Mind you, you could not do subsequent filtering on the lists because they are not QuerySets.
作为此答案的补充,您可以进行单个查询,然后根据需要在 Python 中进行过滤。请注意,您无法对列表进行后续过滤,因为它们不是 QuerySet。
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))
In this last example, everyone
is a queryset, and active_not_deleted
and active_is_deleted
are Python lists of User objects. The everyone
queryset will only be evaluated once in the first list(everyone)
call, and then the results are cached.
在最后一个示例中,everyone
是一个查询集,active_not_deleted
并且active_is_deleted
是用户对象的 Python 列表。查询集everyone
只会在第一次list(everyone)
调用中评估一次,然后缓存结果。
回答by Cory Madden
The best you can do is:
你能做的最好的是:
active_users = User.objects.filter(active=True)
not_deleted = active_users.filter(is_deleted=False)
deleted = active_users.filter(is_deleted=True)
So the answer to your question may be yes, if I understand it correctly.
所以你的问题的答案可能是肯定的,如果我理解正确的话。
回答by Jayground
1. chain filter method
1. 链式过滤法
not_deleted = User.objects.filter(active=True).filter(is_deleted=False)
@Cory Madden already answered. User.objects.filter(active=True)
returns Queryset. So you can add filter method. active_users.filter(is_deleted=False)
@Cory Madden 已经回答了。User.objects.filter(active=True)
返回查询集。所以你可以添加过滤方法。active_users.filter(is_deleted=False)
2. using Q method
2.使用Q方法
from django.db.models import Q
not_deleted = User.objects.filter(Q(active=True) & Q(is_deleted=False)
It is easier to manage your complicated queryset. What if you want to filter userID is not 3? you can use Q simplye like User.objects.filter(Q(active=True) & ~Q(id = 3))
管理复杂的查询集更容易。如果要过滤userID不是3怎么办?您可以使用 Q simplee 之类的User.objects.filter(Q(active=True) & ~Q(id = 3))
Answer for your comment,
回答你的评论,
Using Q or not, it has same raw query.
无论是否使用 Q,它都有相同的原始查询。
SELECT ... FROM ...
WHERE ("auth_user"."active" = True AND "auth_user"."is_deleted" = False)
Database performance is relating to how often you hit database to extract data or if you use a heavy method like 'Join' when you extract something by FK relationship. So Using Q or not doesn't give you performance difference, because it has same query sentence.
数据库性能与您访问数据库以提取数据的频率有关,或者当您通过 FK 关系提取某些内容时是否使用了像“加入”这样的繁重方法。所以使用 Q 与否不会给您带来性能差异,因为它具有相同的查询语句。
Additionally,
此外,
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)
would not give you performance difference.
不会给你性能差异。
Queryset is lazy. user
and not_deleted
variables have just queryset string. It doesn't hit the database right away when you define variable like above. Anyway, you will hit three times for each variable.
查询集是懒惰的。user
和not_deleted
变量只有查询集字符串。当您像上面一样定义变量时,它不会立即访问数据库。无论如何,您将为每个变量击中 3 次。
回答by Vladyslav
You can filter Queryset so much time that you want, because filter()
returns a new Queryset so after filtering you get filtered Queryset and you can do filter or orderby and another methods that return new QuerySets
您可以根据需要过滤 Queryset,因为会filter()
返回一个新的 Queryset,因此在过滤后您会得到过滤的 Queryset,您可以执行 filter 或 orderby 以及其他返回新 QuerySets 的方法
So you can do this:
所以你可以这样做:
active = User.objects.filter(active=True)
deleted = active.filter(is_deleted=True)
not_deleted = active.filter(is_deleted=False)
All it is because User.objects
- is Queryset and User.objects.filter
also return Queryset.
这一切都是因为User.objects
- 是 Queryset 并且User.objects.filter
还返回 Queryset。