url查询中的Django自定义排序

Posted

技术标签:

【中文标题】url查询中的Django自定义排序【英文标题】:Django custom ordering in url queries 【发布时间】:2019-05-19 00:01:31 【问题描述】:

更新二

很遗憾,@Reza Torkaman Ahmadi 的想法最终没有成功。这是因为我们的程序有一个依赖于 get_queryset 的过滤函数,而在我们的视图中覆盖 get_queryset 方法会弄乱该函数。

所以,我和我的搭档讨论了这个问题,这就是他的想法。

class OrderbyFilter(filters.OrderingFilter): def get_ordering(self, request, queryset, view): """ Ordering is set by a comma delimited ?$orderby=... query parameter. Extends the OrderingFilter of the django rest framework to redefine ordering parameters to "asc" and "desc". """ params = request.query_params.get(self.ordering_param) if params: field_queries = [param.strip() for param in params.split(',')] fields = [] for field_query in field_queries: field_query = field_query.split() if len(field_query) <= 2: while "asc" in field_query: field_query.remove("asc") for i, field in enumerate(field_query): if field == "desc": field_query[i-1] = "-" + field_query[i-1] while "desc" in field_query: field_query.remove("desc") fields.append(field_query[0]) else: fields.append([param.strip() for param in params.split(',')]) ordering = self.remove_invalid_fields(queryset, fields, view, request) if ordering: return ordering return self.get_default_ordering(view)

基本上,这个函数覆盖了 Django REST 的源代码,特别是 OrderingFilter 中的 get_ordering 函数。它的作用是,如果 'asc' 在字段之后的查询中,它将删除它并像正常一样对待它(对于正常的提升排序)

否则,如果 'desc' 存在,它会删除 'desc',并应用连字符。

更新已回答。应用了@Reza Torkaman Ahmadi 的想法,在修改它以满足我的需要后效果很好。谢谢老哥!

目前,在 Django API REST 框架中,如果用户想要查看按升序或降序排列的列表,他们必须执行以下操作:

'Datastream&order_by=-name' 按降序显示名称 'Datastream&order_by=name' 按升序显示名称。

我想进行自定义查询,其中输入“Datastream&order_by=asc name”将按升序排列名称,而“desc name”将按降序排列。

我查看了 REST 框架的一些源代码,但我可能看错了地方。对我应该做什么感到困惑。有什么想法吗?

【问题讨论】:

只是展示它现在是如何实现的。 @SergeyPugach 我不明白你的意思。我这样做的原因是为了匹配某个 API 标准。需要使用“desc” 【参考方案1】:

您可以按照自己的方式进行操作。像这样:

class DatastreamViewSet(ModelViewSet):

    def get_queryset(self):
        queryset = super(DatastreamViewSet, self).get_queryset()

        order_by = self.request.query_params.get('order_by', '')
        if order_by:
            order_by_name = order_by.split(' ')[1]
            order_by_sign = order_by.split(' ')[0]
            order_by_sign = '' if order_by_sign == 'asc' else '-'
            queryset = queryset.order_by(order_by_sign + order_by_name)

        return queryset

这将查找查询参数order_by,如果提供则将其按空格分隔,第一个将指示在 order_by 过滤器上使用 + 或 - 符号,第二个将是它的名称。所以把它们放在一起并创建一个文本,将它传递给order_by,然后你就可以开始了。

例如:

?order_by=asc name

在 django 中会这样 =>

return queryset.order_by('name')

【讨论】:

谢谢伙计。我将它应用于我自己的程序并对其进行了一些修改以满足我的需要(确保它不会干扰我的过滤功能等)效果很好!我很感激他。 任何时候我的朋友 :) 不错!我添加了一个额外的检查,只允许它用于某些字段名称。我不确定是否会通过符号更改顺序以使其更明确。【参考方案2】:

Django Rest Framework 的标准方式:

from rest_framework.filters import OrderingFilter

然后在您的 APIView 或 ViewSet 上

filter_backends = (OrderingFilter)
ordering_fields = ['field_name']

查询参数为ordering,也支持逆序。

GET https://example.com/?ordering=-field_name

【讨论】:

应该是 [OrderingFilter] 但这是一种更好的方法

以上是关于url查询中的Django自定义排序的主要内容,如果未能解决你的问题,请参考以下文章

从显示自定义字段的 Django 模型呈现可排序表的最佳方法?

CAML查询中的自定义排序顺序

SOLR查询过滤结果中的自定义排序?

Django 管理员:自定义排序

GraphQL 排序自定义类型

Django admin:如何通过自定义方法对列进行排序