Django-filter и django custom pagination с ModelViewSet
Я реализовал modelviewset с django-filter и django default pagination в сочетании. Он работает нормально, когда я использую либо django-filter, либо django pagination. Но когда они используются одновременно, я получаю дублирующиеся результаты в ответе.
Как правильно использовать пагинацию в django-filter с CBV?
class TableMetaView(ModelViewSet):
"""
This will be used to create new tables.
You require to add the table fields in json request and also the job request associated with that
table.
If you want to create new table then pass CREATE NEW TABLE
In response you will get the table list along with the job request for each tables
"""
serializer_class = TableMetaSerializer
queryset = TableMeta.objects.all()
renderer_classes = [JSONRenderer]
filterset_fields = [
"schema_name",
"type",
"status",
"grouping__name",
"dataset__name",
]
ordering_fields = ["created_on", "modified_on"]
ordering = ["-modified_on"]
pagination_class = StandardResultsSetPagination
permission_classes = [
UserHasDatasetChangeAccess & IsTableEditable,
]
def get_queryset(self):
if getattr(self, "swagger_fake_view", False):
# queryset just for schema generation metadata
return TableMeta.objects.none()
return TableMeta.objects.filter(
dataset=get_object_or_404(DataSet, id=self.request.META.get(DATASET_ID, ""))
)
После долгих поисков мне удалось сделать некоторые изменения, и теперь код работает нормально с django-filters и пагинацией.
custom_pagination.py
from collections import OrderedDict
from constance import config
from rest_framework.pagination import ( # noqa
CursorPagination,
LimitOffsetPagination,
PageNumberPagination,
)
from rest_framework.response import Response
class MyPagination(PageNumberPagination):
page_size = 5
page_size_query_param = "page_size"
max_page_size = 50
def get_paginated_response(self, data):
return Response(
OrderedDict(
{
"next": self.get_next_link(),
"previous": self.get_previous_link(),
"results": data,
}
)
)
views.py
class TableMetaView(ModelViewSet):
"""
This will be used to create new tables.
You require to add the table fields in json request and also the job request associated with that
table.
If you want to create new table then pass CREATE NEW TABLE
In response you will get the table list along with the job request for each tables
"""
serializer_class = TableMetaSerializer
queryset = TableMeta.objects.all()
renderer_classes = [JSONRenderer]
filterset_class = TableFilter
ordering_fields = ["created_on", "modified_on"]
ordering = ["-modified_on"]
pagination_class = MyPagination
permission_classes = [
UserHasDatasetChangeAccess & IsTableEditable,
]
def get_queryset(self):
if getattr(self, "swagger_fake_view", False):
# queryset just for schema generation metadata
return TableMeta.objects.none()
return TableMeta.objects.filter(
dataset=get_object_or_404(DataSet, id=self.request.META.get(DATASET_ID, ""))
)
def list(self, request: Request, *args: Any, **kwargs: Any) -> Response:
filtered_qs = self.filterset_class(request.GET, queryset=self.get_queryset()).qs
page = self.paginate_queryset(queryset=filtered_qs)
serializer = self.serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
custom_filter.py
class TableFilter(django_filters.FilterSet):
class Meta:
model = TableMeta
fields = {
"name": ["exact", "icontains"],
"schema_name": ["exact"],
"type": ["exact"],
"status": ["exact"],
"grouping__name": ["exact"],
"dataset__name": ["exact"],
}
Также необходимо установить порядок по умолчанию
models.py
class TableMeta(models.Model):
class Meta:
ordering = ['-modified_on'] # list of fields here
После этого django-фильтры и пагинация работают нормально в ModelViewSet.