Closed ad-m closed 9 years ago
Oh, here is it:
class StaffCaseFilter(CrispyFilterMixin, django_filters.FilterSet):
name = django_filters.CharFilter(label=_("Subject"), lookup_type='icontains')
client = UserChoiceFilter(label=_("Client"))
created_by = UserChoiceFilter(label=_("Created by"))
created_on = django_filters.DateRangeFilter(label=_("Created on"))
last_send = django_filters.DateRangeFilter(label=_("Last send"))
last_action = django_filters.DateRangeFilter(label=_("Last action"))
class Meta:
model = Case
fields = ['status', 'client', 'name', 'created_on', 'last_send', 'last_action']
order_by = (
('default', _('Default')),
('deadline', _('Dead-line')),
('pk', _('ID')),
('client', _('Client')),
('created_on', _('Created on')),
('last_send', _('Last send')),
('last_action', _('Last action')),
)
def get_order_by(self, order_choice):
if order_choice == 'default':
return ['-deadline', 'status', '-last_send', '-last_action']
return [order_choice]
👍
why is it not possible to add multiple ordering values with the query string, similar to the OrderingFilter
of DRF? See http://www.django-rest-framework.org/api-guide/filtering/#orderingfilter
Referring to the example above, I'd like to do:
?o=client,created_on
@sehmaschine Just for reference: the new OrderingFilter in 0.15 should support this.
@blueyed great, thanks.
I created OrderingFilterExtened for this purposes https://github.com/soldovskij/OrderingFilterExtened
Example:
class UserFilter(FilterSet):
order_by = OrderingFilterExtened(
fields_many=(
('full_name', ('first_name', 'last_name'), ('-first_name', '-last_name')),
),
fields=(
('email', 'email'), # model field name, parameter name
('last_login', 'last_login'),
('date_joined', 'date_joined'),
),
)
class UserListAPIView(UsersPermissionQuerysetMixin, generics.ListAPIView):
queryset = User.objects.all()
permission_classes = (permissions.IsAuthenticated,)
serializer_class = UserListSerializer
pagination_class = LimitOffsetPagination
filterset_class = UserFilter
Request example:
api/v2/users/order_by=full_name
or api/v2/users/order_by=-full_name
As the link above no longer works, another implementation of an extended OrderingFilter
that supports ordering by multiple fields and also ordering by complex expressions:
class ExtendedOrderingFilter(OrderingFilter):
def filter(self, qs, value):
if value in EMPTY_VALUES:
return qs
ordering = []
for param in value:
fields = self.param_map[param.removeprefix('-')]
if not isinstance(fields, tuple):
fields = (fields, )
for field in fields:
if isinstance(field, str):
field = F(field)
ordering.append(field.desc() if param.startswith('-') else field)
return qs.order_by(*ordering)
Usage:
class UserFilter:
sort = ExtendedOrderingFilter(fields=[
('email', 'email'), # sort by regular field
(Length('username'), 'username'), # sort by expression
(('first_name', 'last_name'), 'name'), # sort by multiple fields
])
Thank you @oxan! Your fix has been helpful for me. Just one thing to note - when value
includes "-" prefix, it considers both ordering values as descending. The same goes for ascending. So the direction of the ordering values depends on the param
passed.
In my case, I have a fixed secondary ordering factor called "name". So when it orders by "email", I want to order it by "name" (ascending) as secondary ordering factor. Here is what worked for me:
class ExtendedOrderingFilter(filters.OrderingFilter):
NAME_FIELD = "name"
def filter(self, qs, value):
if value in EMPTY_VALUES:
return qs
# If "name" is not primary ordering, order by it as secondary factor
if self.NAME_FIELD not in value:
value += [self.NAME_FIELD]
return super().filter(qs, value)
class UserFilter(filters.FilterSet):
ordering = ExtendedOrderingFilter(
fields=(
("email", "email"),
("name", "name"),
)
)
Hello,
I am would like to ask about support ordering by multiple fields at once like:
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
I can see it fail:Result:
Is there a easy way to obtain such a result?
Greetings,