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.

Вернуться на верх