查询后可以过滤查询集吗?Django的

Dor*_*ora 14 python mysql django postgresql

对不起,如果问题听起来很奇怪.我只是想知道当我已经有一个查询集时是否有可能创建新的查询集.

比如这里......

 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
Run Code Online (Sandbox Code Playgroud)

什么我的问题是......对not_deletedis_deleted他们都有积极的是相同的真正everyone有使用一个可能的方式everyone,然后以某种方式过滤掉is_deleted=Trueis_deleted=False?那么我相信如果可能的话,查询会更快更好吗?

所有这三个变量everyone,not_deleted并且is_deleted将被用于别的东西.

希望我能清楚明白我的问题.

提前致谢.

A. *_*arr 17

是的,您可以重用现有的查询集.

everyone = User.objects.filter(is_active=True)
active_not_deleted = everyone.filter(is_deleted=False)
active_is_deleted = everyone.filter(is_deleted=True)
Run Code Online (Sandbox Code Playgroud)

事实上,这个代码块甚至不会对数据库执行查询,因为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)
Run Code Online (Sandbox Code Playgroud)

推荐阅读:

作为这个答案的补充,您可以进行单个查询,然后在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))
Run Code Online (Sandbox Code Playgroud)

在最后一个示例中,everyone是一个查询集,active_not_deleted并且active_is_deleted是User对象的Python列表.查询集everyone将仅在第一次list(everyone)调用中计算一次,然后缓存结果.


Jay*_*und 5

1. 链式过滤法

not_deleted = User.objects.filter(active=True).filter(is_deleted=False)
Run Code Online (Sandbox Code Playgroud)

@Cory Madden 已经回答了。User.objects.filter(active=True)返回查询集。所以你可以添加过滤方法。active_users.filter(is_deleted=False)

2.使用Q方法

from django.db.models import Q

not_deleted = User.objects.filter(Q(active=True) & Q(is_deleted=False)
Run Code Online (Sandbox Code Playgroud)

管理复杂的查询集更容易。如果要过滤userID不是3怎么办?您可以使用 Q simplee 之类的User.objects.filter(Q(active=True) & ~Q(id = 3))


回答你的评论,

无论是否使用 Q,它都有相同的原始查询。

SELECT ... FROM ... 
WHERE ("auth_user"."active" = True AND "auth_user"."is_deleted" = False)
Run Code Online (Sandbox Code Playgroud)

数据库性能与您访问数据库以提取数据的频率有关,或者当您通过 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)
Run Code Online (Sandbox Code Playgroud)

不会给你性能差异。

查询集是懒惰的。usernot_deleted变量只有查询集字符串。当您像上面一样定义变量时,它不会立即访问数据库。无论如何,您将为每个变量击中 3 次。


Cor*_*den 4

你能做的最好的事情是:

active_users = User.objects.filter(active=True)
not_deleted = active_users.filter(is_deleted=False)
deleted = active_users.filter(is_deleted=True)
Run Code Online (Sandbox Code Playgroud)

所以如果我理解正确的话,你的问题的答案可能是肯定的。