#django #django-rest-framework
#python #django #django-rest-framework #django-viewsets
Вопрос:
Я создал конечную точку API, используя Django Rest Framework, ее можно фильтровать по двум параметрам. Я пытаюсь сделать следующее: когда нет фильтра, он должен получить x количество записей, в то время как при наличии одного или нескольких фильтров ему необходимо получить больше записей. Итак, в основном мне нужно изменить разбивку на страницы, если есть фильтры.
Вот что я попробовал:
class My_View(viewsets.ModelViewSet):
http_method_names = ['get']
serializer_class = My_Serializer
pagination_class = StandardResultsSetPagination
def get_queryset(self):
valid_filters = {
'Name': 'Name',
'Date': 'Unix__gte',
}
filters = {valid_filters[key]: value for key, value in self.request.query_params.items() if key in valid_filters.keys()}
if len(filters) == 0:
pagination_class = StandardResultsSetPagination
else:
pagination_class = LargeResultsSetPagination
queryset = My_Model.objects.filter(**filters)
return queryset
Что должен делать этот код, так это установить стандартную нумерацию страниц 100, если фильтра нет, и 200, если есть фильтры.
Этот код не работает, разбивка на страницы всегда будет установлена на StandardResultsSetPagination
, и она не изменяется. Я думаю, это потому get_queryset
, что вызывается после установки разбивки на страницы, поэтому его нельзя будет установить позже. Есть ли какой-нибудь способ сделать это?
Ответ №1:
Я знаю, что это решаемая проблема, но здесь более динамичный способ. создайте функцию, которая возвращает PageNumberPagination
подкласс class с dynamic page_size
(вы также можете добавить другие атрибуты, чтобы сделать их динамическими)
from rest_framework.pagination import PageNumberPagination
def customPagination(page_size):
return type("SubClass", (PageNumberPagination,), {"page_size": page_size})
class MyViewA(viewsets.ModelViewSet):
pagination_class = customPagination(page_size=20)
...
class MyViewB(viewsets.ModelViewSet):
pagination_class = customPagination(page_size=50)
...
Ответ №2:
Вам нужно будет переопределить get_page_size
метод вашего класса разбивки на страницы:
from rest_framework.pagination import LimitOffsetPagination
valid_filters = {'Name', 'Date'}
def _has_valid_filters(iterable):
return not valid_filters.isdisjoint(iterable)
class MyPagination(LimitOffsetPagination):
def get_page_size(self, request):
if _has_valid_filters(request.query_params.items()):
return 200
else:
return 100
class MyView(viewsets.ModelViewSet):
pagination_class = MyPagination
...
Комментарии:
1. Этот ответ работает, когда я передаю query_params без метода caalling item. в противном случае он будет возвращать False каждый раз. мне нравятся _has_valid_filters(запрос. query_params)