使用自定义排序依据的 DRF 游标分页



>我需要对成员模型进行一些自定义排序,如下所示(简化(:

class User():
username = models.CharField()
# ...
class Member():
user = models.ForeignKey(User)  # not required
invite_email = models.EmailField()
# ...

我需要按以下方式对成员的查询集进行排序:

  • 没有用户集的成员排在最后;
  • 用户用户名的字母顺序排序(不区分大小写(,如果成员没有用户,则按invite_email排序。

我可以用django进行适当的排序:

queryset.order_by(Lower('user__username').asc(nulls_last=True), 'invite_email')

我认为我可以覆盖 order_by 方法来应用我的自定义排序。

我的问题来自DRF光标分页。从文档中阅读,似乎排序应该是一个字符串,或者一般来说是一个不变的值。但是,当我根据需要使用 Lower 表达式对查询集进行排序时,游标分页类中收到的排序是 OrderBy 对象。这样做,paginate_queryset方法不可用。

我觉得很奇怪,您无法对 DRF 分页类应用自定义过滤。我错过了什么吗?

提前感谢您的任何提示!

您可以为项目使用不同类型的分页。 为什么选择光标分页?

文档中的详细信息:

https://www.django-rest-framework.org/api-guide/pagination/#cursorpagination

基于游标的分页比其他方案更复杂。它还要求结果集呈现固定的顺序,并且不允许客户端任意索引到结果集中。但是,它确实提供了以下好处:

提供一致的分页视图。如果使用得当,CursorPagiation 可确保客户端在分页记录时永远不会看到相同的项目两次,即使在分页过程中其他客户端插入新项目也是如此。 支持使用非常大的数据集。对于非常大的数据集,使用基于偏移的分页样式进行分页可能会变得效率低下或无法使用。相反,基于游标的分页方案具有固定时间属性,并且不会随着数据集大小的增加而减慢速度。

此外,如果检查光标分页的实现,您将看到:

...
assert '__' not in ordering, (
'Cursor pagination does not support double underscore lookups '
'for orderings. Orderings should be an unchanging, unique or '
'nearly-unique field on the model, such as "-created" or "pk".'
)
...
assert isinstance(ordering, (six.string_types, list, tuple)), (
'Invalid ordering. Expected string or tuple, but got {type}'.format(
type=type(ordering).__name__
)

此实现特别禁止使用字符串的简单基于字段的排序以外的其他订单选项。

如果您没有任何超大型数据集,则可能需要选择其他分页实现,例如Page。

基本上,您始终可以创建自己的分页器类并覆盖paginate_queryset并添加自定义排序。

最新更新