Reputation: 4339
i use model with Meta
ordering = ['-published_date']
Now in view:
class InvoiceViewSet(viewsets.ModelViewSet):
queryset = Invoice.objects.all()
serializer_class = InvoiceSerializer
filter_fields = ('table',)
And serializer:
class InvoiceSerializer(serializers.ModelSerializer):
items = ItemSerializer(many=True, allow_add_remove=True)
class Meta:
model = Invoice
fields = ('id', 'items', 'table', 'published_date')
But this ordering doesn't work, it shows me ordering ASC, and i need DESC, it doesn't affect order at all.
What am i doing wrong?
Upvotes: 37
Views: 57502
Reputation: 366
If anyone's coming here from google for 'How to order django-filters queryset'.
There's OrderingFilter in django-filters, which you can use to add the order_by functionality. The example code from the docs looks like this :
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']
Where o is the name of the query param.
So if you hit www.domain.com/o=username
. It will return the queryset ordered by username. If you want to order_by in descending order. Just do www.domain.com/o=-username
(notice the - before username).
Upvotes: 0
Reputation: 457
For Django REST Framework you can use 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')
Upvotes: 31
Reputation: 4339
Solution is to override filter_queryset
:
def filter_queryset(self, queryset):
queryset = super(InvoiceViewSet, self).filter_queryset(queryset)
return queryset.order_by('-published_date')
Upvotes: 24
Reputation: 1088
@Mirza Delic answer works but does not keep the ordering comming from 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)
This works for me and for other people I hope.
Upvotes: 7
Reputation: 33901
If your model does have an ordering it really will be reflected in the list view by default. I'd suggest overriding get_queryset()
and debugging the return result there, or else explicitly adding the ordering to the queryset.
For example:
queryset = Invoice.objects.all().order_by('-published_date')
Wondering if it's possible you've configured a filter that's overriding the ordering. Worth testing what happens if you turn all filters off. I see you have the filter_fields
attribute set, so assuming you've got something like this in your settings...
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',)
}
If you comment that out does that fix things?
Upvotes: 34