Django REST Framework CURSOR分页何时过期?

时间:2019-05-13 14:47:09

标签: python django django-rest-framework

Django REST Framework中使用CURSOR分页时,它使用cursor之类的?cursor=xxxxxxx查询参数(也许是数据库游标ID?),并且我认为游标将在同时使它不再可用。

我的假设是对的吗?如果是这样,它什么时候过期?

1 个答案:

答案 0 :(得分:1)

光标分页不使用某些外部光标。它仅使用分页中模型的字段之一。此字段必须唯一,并且必须始终使用此字段对视图的源查询集进行排序。

让我们看一下示例:

models.py

class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    content = models.TextField()

    created = models.DateTimeField(auto_now_add=True, unique=True)

serializers.py

class BlogPostListSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ['title', 'description', 'created']

views.py

class BlogPostCursorPagination(CursorPagination):
    page_size = 5
    ordering = '-created'

class BlogPostListView(ListAPIView):
    queryset = BlogPost.objects.all().order_by('-created')
    serializer_class = BlogPostListSerializer
    pagination_class = BlogPostCursorPagination

结果:

GET /posts/
{
    "next": "http://127.0.0.1:8000/posts/?cursor=cD0yMDE5LTA1LTEzKzE1JTNBNTYlM0EzNy4xMjI4NjUlMkIwMCUzQTAw",
    "previous": null,
    "results": [
        {
            "title": "Latest post",
            "description": "This is the latest post",
            "created": "2019-05-13T15:57:08.574475Z"
        },
        {
            "title": "Previous post",
            "description": "This post was created before the latest one",
            "created": "2019-05-13T15:57:00.971509Z"
        },
        {
            "title": "2nd previoust post",
            "description": "This one was created even before",
            "created": "2019-05-13T15:56:53.053740Z"
        },
        {
            "title": "3rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:43.804315Z"
        },
        {
            "title": "4rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:37.122865Z"
        }
    ]
}

如您所见,在下一个链接中有一些“垃圾”设置为光标。这不仅仅是垃圾,这是当前页面上最后一项的created字段的base64编码值。就这样...

如果您单击该链接,则django-rest-framework将对其进行解码,并在此之后显示5个元素(不包括其自身)。它很简单:

BlogPost.objects.filter(created__lt=datetime(2019, 5, 13, 15, 56, 37, 122865, tzinfo=utc))

请注意,我们正在使用__lt,因为项目的顺序是相反的:最新的记录在前。

因此,如果您修改该光标,并将DateTime替换为列表中第二个帖子的DateTime,您将获得3到7的帖子:

GET /posts/?cursor=cD0yMDE5LTA1LTEzKzE1JTNBNTclM0EwMC45NzE1MDklMkIwMCUzQTAw
{
    "next": null,
    "previous": "http://127.0.0.1:8000/posts/?cursor=cj0xJnA9MjAxOS0wNS0xMysxNSUzQTU2JTNBNTMuMDUzNzQwJTJCMDAlM0EwMA%3D%3D",
    "results": [
        {
            "title": "2nd previoust post",
            "description": "This one was created even before",
            "created": "2019-05-13T15:56:53.053740Z"
        },
        {
            "title": "3rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:43.804315Z"
        },
        {
            "title": "4rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:37.122865Z"
        },
        {
            "title": "5rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:29.501963Z"
        },
        {
            "title": "6rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:22.033332Z"
        }
    ]
}

此外,没有验证该游标指向的对象是否存在于数据库中。如果您尝试在第二个帖子之后稍稍设置时间戳记,则会收到2到6之间的帖子:

GET /posts/?cursor=cD0yMDE5LTA1LTEzKzE1JTNBNTclM0EwMC45NzE1MTAlMkIwMCUzQTAw
{
    "next": "http://127.0.0.1:8000/posts/?cursor=cD0yMDE5LTA1LTEzKzE1JTNBNTYlM0EyOS41MDE5NjMlMkIwMCUzQTAw",
    "previous": "http://127.0.0.1:8000/posts/?cursor=cj0xJnA9MjAxOS0wNS0xMysxNSUzQTU3JTNBMDAuOTcxNTA5JTJCMDAlM0EwMA%3D%3D",
    "results": [
        {
            "title": "Previous post",
            "description": "This post was created before the latest one",
            "created": "2019-05-13T15:57:00.971509Z"
        },
        {
            "title": "2nd previoust post",
            "description": "This one was created even before",
            "created": "2019-05-13T15:56:53.053740Z"
        },
        {
            "title": "3rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:43.804315Z"
        },
        {
            "title": "4rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:37.122865Z"
        },
        {
            "title": "5rd previous post",
            "description": "And so on...",
            "created": "2019-05-13T15:56:29.501963Z"
        }
    ]
}