Django-rest-framework: 查询集更改时 CursorPagination 的 IndexError

创建于 2019-03-11  ·  4评论  ·  资料来源: encode/django-rest-framework

清单

  • [X] 我已经确认该问题存在于 Django REST 框架的master分支中。
  • [x] 我在打开和关闭的工单中搜索了类似的问题,但找不到重复项。
  • [x] 这不是用法问题。 (那些应该被引导到讨论组。)
  • [x] 这不能作为第三方库处理。 (我们更喜欢在可能的情况下以第三方库的形式提供新功能。)
  • [x] 我已将问题简化为最简单的情况。
  • [x] 我已将失败的测试包含为拉取请求。 (如果您无法这样做,我们仍然可以接受该问题。)

重现步骤

  1. 启用光标分页
  2. 制作足够有分页的项目
  3. 转到第 2 页
  4. 删除外壳中的所有项目
  5. 刷新页面
  6. 查看错误

预期行为

老实说,我不确定,也许是空白页。

实际行为

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

最有用的评论

感谢@ewjoachim@tomchristie 👍

所有4条评论

我要试一试。 如果到 4 月 15 日没有我的消息,请考虑我不再关注它。

作为记录,我无法在遵循票证的确切步骤时进行 repoduce,但是如果我尝试返回到第 1 页,那么我有相同的回溯。

添加一些信息:光标分页可能有 3 个参数:位置、偏移量和光标。 该错误在以下情况下触发:

  • 您所在的页面不再包含任何对象,因为它们已被删除(这有效并返回一个空列表)
  • 即使在重新加载后,指向上一页的链接也包含一个带有偏移量且没有位置的光标。
  • 按照此链接会导致 500

这是因为self.page属性为空,假设页面中没有“唯一”元素,假设页面仅包含具有相同位置的元素,因此算法解析为使用偏移量- 基于排序。

以下评论:

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

...包含错误。 如果页面为空,则此假设是错误的。

修复逻辑并告诉算法检查页面是否为空,然后将位置设置为previous_position / next_position就足以摆脱这个错误。

公关会跟进。

感谢@ewjoachim@tomchristie 👍

此页面是否有帮助?
0 / 5 - 0 等级