我构建了很多增删改查应用程序(惊喜),但我想不出什么情况下需要使用调用 none() 将创建一个永远不返回任何对象且在访问结果时不执行任何查询的QuerySet。qs.none() QuerySet 是 EmptyQuerySet 的一个实例。
none()
。为什么会有人想要返回一个EmptyQuerySet呢?
我构建了很多增删改查应用程序(惊喜),但我想不出什么情况下需要使用调用 none() 将创建一个永远不返回任何对象且在访问结果时不执行任何查询的QuerySet。qs.none() QuerySet 是 EmptyQuerySet 的一个实例。
none()
。通常情况下,如果你需要提供一个QuerySet
,但没有可用的 - 例如调用方法或提供给模板。
优点是,如果你知道没有结果(或不想要结果),但你仍然需要一个结果,none()
将不会访问数据库。
举个不太现实的例子,假如你有一个API可以查询您的权限。如果帐户尚未确认,由于你已经拥有了Account
对象,并且你可以看到account.is_activated
为False
,你可以通过使用Permission.objects.none()
跳过检查数据库的权限。
def get_me_queryset(conditionA, conditionB, conditionC):
queryset = Model.objects.none()
if conditionA:
queryset |= some_complex_computation(conditionA)
elif conditionB:
queryset |= some_complex_computation(conditionB)
if conditionC:
queryset |= some_simple_computation(conditionC)
return queryset
get_me_queryset
几乎总是应该返回 django.db.models.query.QuerySet
的实例(因为好的编程),而不是 None
或 []
,否则它将在以后引入头痛的问题。
这样即使没有一个条件成立,你的代码仍然保持完整。不再需要类型检查。
对于那些不理解此处使用 |
运算符的人:
queryset |= queryset2
queryset = queryset + queryset
QuerySet.none还有另一个用途,当您不知道是否存在对象但又不想引发错误时使用。
例如:
class DummyMixin(object):
def get_context_data(self,**kwargs):
""" Return all the pks of objects into the context """
context = super(DummyMixin, self).get_context_data(**kwargs)
objects_pks = context.get(
"object_list",
Mymodel.objects.none()
).values_list("pk", flat=True)
context["objects_pks"] = objects_pks
.values_list()
或类似方法。如果该方法返回None,则会出现如下错误:
AttributeError:'list' object has no attribute 'values_list'
但是,如果你的子句返回 MyModel.objects.none()
而不是 None
,则调用代码将很高兴,因为返回的数据是一个空查询集而不是None对象。
换句话说,它允许您不混合返回类型(例如“此函数返回QuerySet或None”,这很麻烦)。
最初的回答
在Django文档的其他示例中看到qs.none()
的用法是有益的,特别是当使用查询集初始化模型表单集时,如果您希望结果为空,则给出的示例如下:
formset = AuthorFormSet(queryset=Author.objects.none())
none()用于get_queryset(),根据has_view_or_change_permission()的状态返回空查询集,如下所示:
class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
# ...
def has_view_or_change_permission(self, request, obj=None):
return self.has_view_permission(request, obj) or self.has_change_permission(
request, obj
)
# ...
class InlineModelAdmin(BaseModelAdmin):
# ...
def get_queryset(self, request):
queryset = super().get_queryset(request)
if not self.has_view_or_change_permission(request):
queryset = queryset.none() # Here
return queryset