Django rest framework验证分页限制和偏移

Django rest framework验证分页限制和偏移

问题描述:

默认情况下,Django Rest Framework会忽略针对无效的limitoffset值引发的异常,即使它们不是整数并返回默认限制和偏移值。
还没有min_offsetmin_limit因而它允许在限制和偏移负值。
我需要在我的API中的这些情况下抛出错误。
我建立了一个自定义分页类中重写paginate_queryset方法,使我的验证那里。是否有API来验证最小限制和最小偏移值。我有我自己验证它的下面的代码。Django rest framework验证分页限制和偏移

可以在方法内部为paginator编写验证,因为没有从文档中提及它,或者我需要验证我的viewset方法本身吗?

class CustomPagination(pagination.LimitOffsetPagination): 
    default_limit = 25 
    max_limit = 50 
    min_limit = 1 
    min_offset = 1 
    max_offset = 50 

    def paginate_queryset(self, queryset, request, view=None): 
     limit = request.query_params.get('limit') 
     offset = request.query_params.get('offset') 

     if limit: 
      limit = int(limit) 
      if limit > self.max_limit: 
       raise serializers.ValidationError({"limit" : ["Limit should be less than or equal to {0}".format(self.max_limit)]}) 
      elif limit < self.min_limit: 
       raise serializers.ValidationError({"limit" : ["Limit should be greater than or equal to {0}".format(self.min_limit)]}) 
     if offset: 
      offset = int(offset) 
      if offset > self.max_offset: 
       raise serializers.ValidationError({"offset" : ["Offset should be less than or equal to {0}".format(self.max_offset)]}) 
      elif offset < self.min_offset: 
       raise serializers.ValidationError({"offset" : ["Offset should be greater than or equal to {0}".format(self.min_offset)]}) 

     return super(self.__class__, self).paginate_queryset(queryset, request, view) 
+0

我在想,如果我的回答对您有所帮助你 –

+0

@约翰Moutafis是。我让他们回到DRF IRC频道,他们说这个决定是有意的,开发人员需要验证它。 – xtreak

+0

很高兴听到@xtreak:D!谨慎接受答案? –

如果你看看DRF代码上LimitOffsetPagination你会看到它使用两种方法来解析limitoffset

  • get_limit()

    def get_limit(self, request): 
        if self.limit_query_param: 
         try: 
          return _positive_int(
           request.query_params[self.limit_query_param], 
           strict=True, 
           cutoff=self.max_limit 
          ) 
         except (KeyError, ValueError): 
          pass 
    
        return self.default_limit 
    
  • get_offset()

    def get_offset(self, request): 
        try: 
         return _positive_int(
          request.query_params[self.offset_query_param], 
         ) 
        except (KeyError, ValueError): 
         return 0 
    

正如您所看到的,可能的异常是在这两种方法中处理的。

因此,你可以很容易地覆盖这些方法并没有必要要么推倒重来。
制作方法捕获异常并再次raise它:

class CustomPagination(pagination.LimitOffsetPagination): 
    default_limit = 25 
    max_limit = 50 
    min_limit = 1 
    min_offset = 1 
    max_offset = 50 

    def get_limit(self, request): 
     if self.limit_query_param: 
      try: 
       return _positive_int(
        request.query_params[self.limit_query_param], 
        strict=True, 
        cutoff=self.max_limit 
       ) 
      except (KeyError, ValueError) as e: 
       raise e # Re-raise the caught exception 

     return self.default_limit 

    def get_offset(self, request): 
     try: 
      return _positive_int(
       request.query_params[self.offset_query_param], 
      ) 
     except (KeyError, ValueError) as e: 
      raise e # Re-raise the caught exception 

注:
虽然上述作品,这将是非常不方便的应用程序崩溃的每一个用户传递一个错误的时间对它的争论,你应该考虑使用它。