查询后是否可以过滤queryset?张江

2024-04-20 07:36:45 发布

您现在位置:Python中文网/ 问答频道 /正文

对不起,如果这个问题听起来很奇怪。我只是想知道,如果我已经有了一个queryset,是否有可能创建新的queryset。

例如这里。。。

 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_deletedis_deleted它们都是活动的是真的,与everyone一样,是否有可能使用everyone然后以某种方式过滤掉is_deleted=Trueis_deleted=False?所以我相信如果这可能的话,查询会更快更好,对吧?

所有这三个变量everyonenot_deletedis_deleted都将用于其他用途。

希望我把问题说清楚了。

提前谢谢。


Tags: andfalsetruereturnobjectsthatisnot
3条回答

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

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进行过滤。请注意,不能对列表进行后续筛选,因为它们不是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))

在最后一个示例中,everyone是一个queryset,而active_not_deletedactive_is_deleted是用户对象的Python列表。在第一个list(everyone)调用中,只对everyonequeryset求值一次,然后缓存结果。

你能做的就是:

active_users = User.objects.filter(active=True)
not_deleted = active_users.filter(is_deleted=False)
deleted = active_users.filter(is_deleted=True)

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

一。链过滤法

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)

2。使用Q方法

from django.db.models import Q

not_deleted = User.objects.filter(Q(active=True) & Q(is_deleted=False)

更容易管理复杂的查询集。如果你想过滤用户id不是3怎么办?您可以使用Q simpley likeUser.objects.filter(Q(active=True) & ~Q(id = 3))


回答你的意见

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

SELECT ... FROM ... 
WHERE ("auth_user"."active" = True AND "auth_user"."is_deleted" = False)

数据库性能与您访问数据库以提取数据的频率有关,或者在按FK关系提取数据时使用诸如“Join”之类的重载方法。所以使用Q或不使用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)

不会给你带来性能差异。

奎丽斯特很懒。usernot_deleted变量只有queryset字符串。当您像上面这样定义变量时,它不会立即到达数据库。不管怎样,每个变量都会命中三次。

相关问题 更多 >