Django Rest Framework默认情况下会吞下针对无效limit和offset值引发的异常,即使它们不是整数并返回默认限制和偏移值。
此外,没有min_offset
和min_limit
因此它允许在限制和偏移中使用负值。
我需要在我的API中对这些情况提出错误。
我已经构建了一个自定义分页类来覆盖paginate_queryset
方法并在那里进行了验证。是否有API来验证最小限制和最小偏移值。我有以下代码,我自己验证它。
是否可以在方法中为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 :(得分:1)
如果您查看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
正如您所看到的,可以在这两种方法中处理可能的异常。
因此,您可以轻松覆盖这些方法,也无需重新发明轮子。
使方法捕获异常并再次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
注意:强>
虽然前面提到的工作,但每次用户传递错误的参数时你的应用程序崩溃都会非常不方便,你应该考虑使用它。