ListAPIView自定义分页时返回ValidationError报无len()错误如何解决?
错误原因
get_queryset 方法的设计预期是返回Django QuerySet对象,你在else分支直接返回了异常对象而非抛出异常,DRF后续处理分页、序列化逻辑时会尝试操作这个异常对象(比如调用len()统计数据总条数),因此触发类型错误。
修复方案
方案1:快速修复(直接调整异常抛出逻辑)
把return ValidationError改为抛出异常即可,同时建议使用语义更匹配的PermissionDenied异常(对应HTTP 403权限拒绝状态码),替换代码如下:
from rest_framework.exceptions import PermissionDenied class ProductListAPIView(generics.ListAPIView): serializer_class = ProductSerializer pagination_class = StandardResultsSetPagination permission_classes = (permissions.IsAuthenticated, ) def get_queryset(self): company = self.request.GET['company'] view = self.request.GET['view'] if view=='Pool Operator': emp = list(Employee.objects.filter(company=company).values_list('pk', flat=True)) queryset = Product.objects.filter(owner__in=emp).order_by('-pk') return queryset else: # 抛出异常而非返回异常对象 raise PermissionDenied( {'permission denied': "Can't see user's Products"} )
方案2:规范优化(调整校验逻辑位置)
参数校验、权限校验逻辑不建议放在get_queryset中处理,可以提前到视图的initial方法中执行,更早拦截非法请求,逻辑也更符合DRF的执行流程:
from rest_framework.exceptions import PermissionDenied class ProductListAPIView(generics.ListAPIView): serializer_class = ProductSerializer pagination_class = StandardResultsSetPagination permission_classes = (permissions.IsAuthenticated, ) def initial(self, request, *args, **kwargs): super().initial(request, *args, **kwargs) view = request.GET.get('view', '') if view != 'Pool Operator': raise PermissionDenied( {'permission denied': "Can't see user's Products"} ) def get_queryset(self): company = self.request.GET['company'] emp = list(Employee.objects.filter(company=company).values_list('pk', flat=True)) return Product.objects.filter(owner__in=emp).order_by('-pk')
内容的提问来源于stack exchange,提问作者Rahul Sharma
相关产品推荐
相关产品推荐

