pagenumberpagination list_route framework español as_view python django pagination django-rest-framework django-pagination

python - list_route - Django Rest Framework 3.1 rompe paginación.PaginationSerializer



pagination serializer rest framework (3)

Creo que lo descubrí (al menos en su mayor parte):

Lo que deberíamos haber usado desde el principio es esto:

Simplemente use el paginador incorporado y cambie su views.py a esto:

from rest_framework.pagination import PageNumberPagination class CourseListView(AuthView): def get(self, request, format=None): """ Returns a JSON response with a listing of course objects """ courses = Course.objects.order_by(''name'').all() paginator = PageNumberPagination() # From the docs: # The paginate_queryset method is passed the initial queryset # and should return an iterable object that contains only the # data in the requested page. result_page = paginator.paginate_queryset(courses, request) # Now we just have to serialize the data just like you suggested. serializer = CourseSerializer(result_page, many=True) # From the docs: # The get_paginated_response method is passed the serialized page # data and should return a Response instance. return paginator.get_paginated_response(serializer.data)

Para el tamaño de página deseado, simplemente configure PAGE_SIZE en settings.py :

REST_FRAMEWORK = { ''DEFAULT_PAGINATION_CLASS'': ''rest_framework.pagination.PageNumberPagination'', ''PAGE_SIZE'': 15 }

Debería estar listo ahora con todas las opciones presentes en el cuerpo de la respuesta (contar, enlaces siguientes y anteriores) ordenadas como antes de la actualización.

Sin embargo, hay una cosa más que todavía me preocupa: también deberíamos poder obtener los nuevos controles de paginación html que por alguna razón faltan por ahora ...

Definitivamente podría usar un par de sugerencias más sobre esto ...

Acabo de actualizar a Django Rest Framework 3.1 y parece que todo se desató.

en mi serializers.py estaba teniendo el siguiente código:

class TaskSerializer(serializers.ModelSerializer): class Meta: model = task exclude = (''key'', ...) class PaginatedTaskSerializer(pagination.PaginationSerializer): class Meta: object_serializer_class = TaskSerializer

que funcionaba bien Ahora, con el lanzamiento de 3.1, no puedo encontrar ejemplos sobre cómo hacer lo mismo ya que PaginationSerializer ya no está allí. He intentado subclasificar PageNumberPagination y usar sus métodos predeterminados get_paginated_response y get_paginated_response pero ya no puedo serializar sus resultados.

En otras palabras, mi problema es que ya no puedo hacer esto:

class Meta: object_serializer_class = TaskSerializer

¿Algunas ideas?

Gracias por adelantado



No estoy seguro de si esta es la forma correcta de hacerlo, pero funciona para mis necesidades. Utiliza el Paginator de Django y un serializador personalizado.

Aquí está mi clase de vista que recupera los objetos para la serialización.

class CourseListView(AuthView): def get(self, request, format=None): """ Returns a JSON response with a listing of course objects """ courses = Course.objects.order_by(''name'').all() serializer = PaginatedCourseSerializer(courses, request, 25) return Response(serializer.data)

Aquí está el serializador pirateado que usa el serializador de mi curso.

from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage class PaginatedCourseSerializer(): def __init__(self, courses, request, num): paginator = Paginator(courses, num) page = request.QUERY_PARAMS.get(''page'') try: courses = paginator.page(page) except PageNotAnInteger: courses = paginator.page(1) except EmptyPage: courses = paginator.page(paginator.num_pages) count = paginator.count previous = None if not courses.has_previous() else courses.previous_page_number() next = None if not courses.has_next() else courses.next_page_number() serializer = CourseSerializer(courses, many=True) self.data = {''count'':count,''previous'':previous, ''next'':next,''courses'':serializer.data}

Esto me da un resultado que es similar al comportamiento que dio el antiguo paginador.

{ "previous": 1, "next": 3, "courses": [...], "count": 384 }

Espero que esto ayude. Todavía creo que tiene que haber una mejor manera de hacer esto con la nueva API, pero simplemente no está bien documentado. Si me imagino algo más, editaré mi publicación.

EDITAR

Creo que he encontrado una forma mejor y más elegante de hacerlo con la creación de mi propio paginador personalizado para obtener el comportamiento que solía tener con la antigua clase de Serializador Paginado.

Esta es una clase de paginador personalizada. Sobrecargué la respuesta y los métodos de la página siguiente para obtener el resultado que quiero (es decir ?page=2 lugar de la URL completa).

from rest_framework.response import Response from rest_framework.utils.urls import replace_query_param class CustomCoursePaginator(pagination.PageNumberPagination): def get_paginated_response(self, data): return Response({''count'': self.page.paginator.count, ''next'': self.get_next_link(), ''previous'': self.get_previous_link(), ''courses'': data}) def get_next_link(self): if not self.page.has_next(): return None page_number = self.page.next_page_number() return replace_query_param('''', self.page_query_param, page_number) def get_previous_link(self): if not self.page.has_previous(): return None page_number = self.page.previous_page_number() return replace_query_param('''', self.page_query_param, page_number)

Entonces mi vista del curso es muy similar a la forma en que lo implementó, solo que esta vez utilizando el paginador personalizado.

class CourseListView(AuthView): def get(self, request, format=None): """ Returns a JSON response with a listing of course objects """ courses = Course.objects.order_by(''name'').all() paginator = CustomCoursePaginator() result_page = paginator.paginate_queryset(courses, request) serializer = CourseSerializer(result_page, many=True) return paginator.get_paginated_response(serializer.data)

Ahora obtengo el resultado que estoy buscando.

{ "count": 384, "next": "?page=3", "previous": "?page=1", "courses": [] }

Todavía no estoy seguro de cómo funciona esto para la API de navegación (no utilizo esta función de drf). Creo que también puedes crear tu propia clase personalizada para esto. ¡Espero que esto ayude!