Django-rest-framework: IndexError para CursorPagination cuando cambia el conjunto de consultas

Creado en 11 mar. 2019  ·  4Comentarios  ·  Fuente: encode/django-rest-framework

Lista de Verificación

  • [X] He verificado que ese problema existe en la rama master del marco Django REST.
  • [x] He buscado problemas similares en tickets abiertos y cerrados y no puedo encontrar un duplicado.
  • [x] Esta no es una pregunta de uso. (En su lugar, deben dirigirse al grupo de discusión ).
  • [x] Esto no se puede tratar como una biblioteca de terceros. (Preferimos que la nueva funcionalidad esté en forma de bibliotecas de terceros siempre que sea posible).
  • [x] He reducido el problema al caso más simple posible.
  • [x] He incluido una prueba fallida como una solicitud de extracción. (Si no puede hacerlo, aún podemos aceptar el problema).

pasos para reproducir

  1. Habilitar CursorPagination
  2. Haga suficientes elementos para que haya paginación.
  3. Ir a la página 2
  4. Eliminar todos los elementos dentro del caparazón
  5. Recarga la página
  6. Ver error

Comportamiento esperado

Para ser honesto, no estoy seguro, tal vez una página en blanco.

Comportamiento real

Traceback (most recent call last):
  File "/var/env/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
    return self.application(environ, start_response)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/wsgi.py", line 142, in __call__
    response = self.get_response(request)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 78, in get_response
    response = self._middleware_chain(request)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 36, in inner
    response = response_for_exception(request, exc)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/var/env/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/var/env/lib/python3.6/site-packages/six.py", line 692, in reraise
    raise value.with_traceback(tb)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/var/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/var/env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/var/env/lib/python3.6/site-packages/rest_framework/viewsets.py", line 116, in view
    return self.dispatch(request, *args, **kwargs)
  File "/var/env/lib/python3.6/site-packages/rest_framework/views.py", line 495, in dispatch
    response = self.handle_exception(exc)
  File "/var/env/lib/python3.6/site-packages/rest_framework/views.py", line 455, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/var/env/lib/python3.6/site-packages/rest_framework/views.py", line 492, in dispatch
    response = handler(request, *args, **kwargs)
  File "/var/env/lib/python3.6/site-packages/rest_framework/mixins.py", line 45, in list
    return self.get_paginated_response(serializer.data)
  File "/var/env/lib/python3.6/site-packages/rest_framework/generics.py", line 180, in get_paginated_response
    return self.paginator.get_paginated_response(data)
  File "/var/env/lib/python3.6/site-packages/rest_framework/pagination.py", line 781, in get_paginated_response
    ('previous', self.get_previous_link()),
  File "/var/env/lib/python3.6/site-packages/rest_framework/pagination.py", line 643, in get_previous_link
    compare = self._get_position_from_instance(self.page[0], self.ordering)
IndexError: list index out of range

Comentario más útil

Gracias @ewjoachim y @tomchristie 👍

Todos 4 comentarios

Voy a intentar intentarlo. Si no tengo noticias mías antes del 15 de abril, considere que ya no estoy en eso.

Para el registro, no puedo volver a registrar cuando sigo los pasos exactos del ticket, pero si trato de volver a la página 1, entonces tengo el mismo rastreo.

Añadiendo algo de información: la paginación del cursor puede tener 3 parámetros: posición, desplazamiento y cursor. El error se activa cuando:

  • Estás en una página que ya no contiene objetos, porque fueron eliminados (esto funciona y devuelve una lista vacía)
  • El enlace a la página anterior, incluso después de recargar, incluye un cursor con un desplazamiento y sin posición.
  • Siguiendo este enlace conduce a un 500

Esto se debe a que el atributo self.page está vacío, se supone que no hay ningún elemento "único" en la página, se supone que la página contiene solo elementos que tienen la misma posición y, por lo tanto, el algoritmo se resuelve en utilizar un desplazamiento. pedidos basados ​​en.

El siguiente comentario:

https://github.com/encode/django-rest-framework/blob/29cbe574a384c3bcc09434a3a9c5ff0cb7576b99/rest_framework/pagination.py#L615

... engloba el error. Esta suposición es incorrecta si la página está vacía.

Arreglar la lógica y decirle al algoritmo que verifique si la página está vacía y luego establecer la posición en previous_position / next_position es suficiente para deshacerse de este error.

PR seguirá.

Gracias @ewjoachim y @tomchristie 👍

¿Fue útil esta página
0 / 5 - 0 calificaciones