在Django REST Framework
中使用CURSOR分页时,它使用cursor
之类的?cursor=xxxxxxx
查询参数(也许是数据库游标ID?),并且我认为游标将在同时使它不再可用。
我的假设是对的吗?如果是这样,它什么时候过期?
答案 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"
}
]
}