Django Rest Framework 默认吞下因无效 limit 引发的异常和 offset值,即使它们不是整数并返回默认限制和偏移值。
也没有 min_offset 和 min_limit 因此它允许 limit 和 offset 中的负值。
我需要在我的 API 中对这些情况抛出错误。
我构建了一个覆盖 paginate_queryset 方法的自定义分页类,并在那里进行了验证。是否有 API 来验证最小限制和最小偏移值。我有下面的代码,我自己验证了它。
是否可以在方法内部编写分页器验证,因为文档中没有提及它,还是我需要在我的 View 集方法本身内部进行验证?
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)
请您参考如下方法:
如果您查看 LimitOffsetPagination 上的 DRf 代码你会看到它使用两种方法来解析 limit 和 offset:
-
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 -
def get_offset(self, request): try: return _positive_int( request.query_params[self.offset_query_param], ) except (KeyError, ValueError): return 0
如您所见,可能的异常是在这两个方法中处理的。
因此,您可以轻松覆盖这些方法,也无需重新发明轮子。
让方法捕获异常并再次引发:
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
注意:
尽管上述方法有效,但每次用户向其传递错误参数时应用程序崩溃都会非常不便,您应该考虑使用它。
