You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django & DRF中get_queryset被调用两次,有无更优解决方案?

Django REST Framework中get_queryset重复调用问题

我用Django和REST Framework搭建API项目时遇到个问题:使用DRF通用视图+DjangoModelPermissions编写视图时,get_queryset方法会被调用两次。调试后发现,权限验证环节会调用get_queryset来获取模型以校验用户权限,这属于不必要的操作,数据表较大时会引发性能问题。

现有代码

权限类

class DefaultModelPermissions(DjangoModelPermissions):
    """
    使用django.contrib.auth权限做认证,确保用户已登录且拥有对应模型的view/add/change/delete权限
    仅适用于提供了.queryset属性的视图类
    """
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

class DefaultModelViewPermissions:
    permission_classes = (DefaultModelPermissions,)

视图类

class AgentListCreateView(DefaultModelViewPermissions, generics.ListCreateAPIView):
    serializer_class = serializers.AgentSerializer
    
    def get_queryset(self):
         print('get_queryset')
         return models.Agent.objects.all()

当前解决方案

我重写了has_permission方法,直接从序列化器的Meta类中获取模型,避免调用get_queryset触发不必要的数据库查询:

class DefaultModelPermissions(DjangoModelPermissions):
    """
    使用django.contrib.auth权限做认证,确保用户已登录且拥有对应模型的view/add/change/delete权限
    仅适用于提供了.queryset属性的视图类
    """
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }
    
    def has_permission(self, request, view):
        if not request.user or (
           not request.user.is_authenticated and self.authenticated_users_only):
            return False

        # 避免DefaultRouter的根视图应用权限校验
        if getattr(view, '_ignore_model_permissions', False):
            return True

        # 从序列化器获取模型,避免调用get_queryset触发数据库查询
        if hasattr(view, 'get_serializer_class'):
            model = view.get_serializer_class().Meta.model
        else:
            model = view.serializer_class.Meta.model
        
        perms = self.get_required_permissions(request.method, model)

        return request.user.has_perms(perms)

疑问

想问下有没有更优的解决办法?其他开发者也遇到过这个问题吗?

内容的提问来源于stack exchange,提问作者Chinellow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:32:06