2016-11-14 91 views
1

默認情況下,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!謹慎接受答案? –

回答

1

如果你看看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 

注:
雖然上述作品,這將是非常不方便的應用程序崩潰的每一個用戶傳遞一個錯誤的時間對它的爭論,你應該考慮使用它。