根据Django REST framework documentation,以下两个代码段的行为应相同。
class UserViewSet(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
serializer_class = UserSerializer
queryset = User.objects.all()
但是我的解释方式是,在第一种情况下,查询User.objects.all()
与每个api调用一起运行,在第二种情况下,查询在Web服务器启动时仅运行一次,因为它是类变量。我错了吗 ?至少在我的测试中,尝试模拟User.objects.all将会失败,因为到那时UserViewSet.queryset将已经是一个空的Queryset对象。
请有人向我解释为什么不应该避免使用queryset类参数(例如使用pest和get_queryset代替)? 编辑:用get_queryset替换queryset会使self.queryset在检索方法中未定义,所以我也需要在方法内使用self.get_queryset()...
答案 0 :(得分:2)
来自Django docs:
QuerySet是惰性的–创建QuerySet的行为不涉及任何数据库活动。您可以整天将过滤器堆叠在一起,并且在评估QuerySet之前,Django不会真正运行查询
ModelViewSet
提供了诸如delete
和update
之类的其他操作,您可能需要针对用户模型对它们进行一些限制(例如检查权限,或者您可能不喜欢让用户只需删除其个人资料)
self.queryset
用于路由器以及基本名称和内容,您可以忽略它并在路由器中手动设置基本名称。它不是强制性的,但我认为它使我的代码更具可读性
请注意,当您要对默认查询集执行某些操作(例如基于当前用户的限制def get_queryset
)时,通常使用self.queryset
。因此,如果get_queryset
要返回.objects.all()
或.objects.filter(active=True)
,我建议使用self.queryset
来获得更简洁的代码
note2:如果您决定定义get_queryset
,我建议也定义self.queryset
(如果可能)
note3:始终在视图方法中使用self.get_queryset
,即使您未定义此方法,您可能也需要稍后创建该方法,如果您的视图方法使用self.queryset
,则可能会导致您代码中的一些问题
答案 1 :(得分:0)
添加到 Aliva 的 answer 并引用 DRF 视图集代码,在 get_queryset()
方法定义下它指出:
应始终使用此方法而不是访问 self.queryset
直接,因为 self.queryset
仅被评估一次,并且这些结果
为所有后续请求缓存。如果您需要提供不同的
查询集取决于传入的请求。