【问题标题】:django rest framework queryset doesn't orderdjango rest 框架查询集不排序
【发布时间】:2014-09-19 04:19:42
【问题描述】:

我用Metaordering = ['-published_date']的模型

现在可见:

class InvoiceViewSet(viewsets.ModelViewSet):
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer
    filter_fields = ('table',)

和序列化器:

class InvoiceSerializer(serializers.ModelSerializer):
    items = ItemSerializer(many=True, allow_add_remove=True)

    class Meta:
        model = Invoice
        fields = ('id',  'items', 'table', 'published_date')

但是这个排序不起作用,它显示我在排序 ASC,我需要 DESC,它根本不影响排序。

我做错了什么?

【问题讨论】:

  • 如果您从 shell 调用 Invoice.objects.all() 是否显示 DESC 排序?
  • 是的。这很奇怪。 ://
  • 它必须与 DRF 有关。你的输出是什么样的?
  • 我用rest客户端来查看输出,它只是按ASC排序。视图或序列化程序可能有问题吗?或者有没有其他方法可以做到这一点?
  • 您可以覆盖 get_queryset() 方法,但是,我之前已经这样做过,就像您一样,它对我有用。其他的一定是错的。

标签: python django django-rest-framework


【解决方案1】:

如果您的模型确实有排序 真的 将默认反映在列表视图中。我建议覆盖get_queryset() 并在那里调试返回结果,或者将排序显式添加到查询集中。

例如:

queryset = Invoice.objects.all().order_by('-published_date')

想知道是否有可能您配置了一个覆盖排序的过滤器。值得测试如果您关闭所有过滤器会发生什么。我看到你设置了filter_fields 属性,所以假设你的设置中有这样的东西......

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}

如果您将其注释掉,是否可以解决问题?

【讨论】:

  • 当我对此发表评论时它会起作用。谢谢,现在我可以让它一起工作吗?
  • 简单的解决方法应该是上面列出的.order_by,但下一步 - 为什么使用DjangoFilterBackend 设置显式排序,而不是保留默认值?这是django-filter 中的错误还是REST framework 中的集成问题?
  • 使用queryset = Invoice.objects.all().order_by('-published_date')还是不行:(
  • 好吧,有趣的是,假设 django-filter 然后覆盖了排序。票是github.com/tomchristie/django-rest-framework/issues/1717
【解决方案2】:

解决方案是覆盖filter_queryset:

def filter_queryset(self, queryset):
    queryset = super(InvoiceViewSet, self).filter_queryset(queryset)
    return queryset.order_by('-published_date')

【讨论】:

  • 对于一个简单的功能来说,这是很多开销。我想知道这在过去 4.5 年中是否发生了变化?
【解决方案3】:

对于 Django REST 框架,您可以使用 OrderingFilter

from django_filters import DjangoFilterBackend
from rest_framework import viewsets, filters


class InvoiceViewSet(viewsets.ModelViewSet):
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer

    filter_backends = (DjangoFilterBackend, filters.OrderingFilter)

    # Explicitly specify which fields the API may be ordered against
    ordering_fields = ('items', 'table', 'published_date')

    # This will be used as the default ordering
    ordering = ('-published_date')

【讨论】:

  • 对于那些在 DRF 中手动通过查询参数订购的人来说,这在几分钟内解决了几个小时的头痛问题。谢谢!
  • 如果有人在使用 django-filters 并且不能使用另一个后端。请参阅下面的答案。
【解决方案4】:

@Mirza Delic 回答有效,但不能保持来自 request.QUERY_PARAMS 的排序。

class YOUR_VIEW_SET(viewsets.ModelViewSet):
    #your code here
    ordering_filter = OrderingFilter()

    def filter_queryset(self, queryset):
        queryset = super(YOUR_VIEW_SET, self).filter_queryset(queryset)
        return self.ordering_filter.filter_queryset(self.request, queryset, self)

这对我和我希望的其他人都有效。

【讨论】:

    【解决方案5】:

    如果有人从谷歌来这里询问“如何订购 django-filters 查询集”。

    在 django-filters 中有 OrderingFilter,您可以使用它来添加 order_by 功能。 文档中的示例代码如下所示:

    class UserFilter(FilterSet):
    account = CharFilter(field_name='username')
    status = NumberFilter(field_name='status')
    
    o = OrderingFilter(
        # tuple-mapping retains order
        fields=(
            ('username', 'account'),
            ('first_name', 'first_name'),
            ('last_name', 'last_name'),
        ),
    
        # labels do not need to retain order
        field_labels={
            'username': 'User account',
        }
    )
    
    class Meta:
        model = User
        fields = ['first_name', 'last_name']
    

    其中 o 是查询参数的名称。 所以如果你点击www.domain.com/o=username。它将返回按用户名排序的查询集。如果你想按降序排序。只需执行www.domain.com/o=-username(注意用户名前的 -)。

    【讨论】:

      猜你喜欢
      • 2015-05-08
      • 2014-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-25
      • 2016-08-06
      • 2016-01-10
      • 1970-01-01
      相关资源
      最近更新 更多