Excellent :)
So far I have working method b) that involves building a mapping and using it to replace, which duplicates some of the code from remove_invalid_fields, so I am on the fence about whether it would be better/neater implemented directly in remove_invalid_fields; what do you think?
class SerializerFieldOrderingFilter(OrderingFilter):
def rewrite_to_source_fields(self, ordering, view):
# Rewrite Serializer fields to their source fields
serializer_class = getattr(view, 'serializer_class')
if serializer_class is None:
# Nothing to rewrite
return ordering
# get mapping of field_name to source
source_field_mapping = {
field_name: field.source or field_name for field_name, field in serializer_class().fields.items()
}
# rewrite to source field
for k, field in enumerate(ordering):
direction = '-' if field[0] == '-' else ''
if field.lstrip('-') in source_field_mapping.keys():
ordering[k] = direction + source_field_mapping[field.lstrip('-')]
return ordering
def filter_queryset(self, request, queryset, view):
ordering = self.get_ordering(request)
if ordering:
# Rewrite Serializer fields as their source fields
ordering = self.rewrite_to_source_fields(ordering, view)
# Skip any incorrect parameters
ordering = self.remove_invalid_fields(queryset, ordering, view)
if not ordering:
# Use 'ordering' attribute by default
ordering = self.get_default_ordering(view)
if ordering:
return queryset.order_by(*ordering)
return queryset