Filtering and Ordering

During a get list view, it is useful to be able to filter or rearrange the results. Django-Conduit provides a few helpful properties and hooks to to filter your resources.

Server Side Filters to Limit Access

The default_filters dict on a ModelResource’s Meta class will apply the listed queryset filters before fetching results. The keys in default_filters ought to be a valid Queryset filter method for the specified model. Here is an example that only returns Foo objects that have a name starting with the the word ‘lamp’:

class FooResource(ModelResource):
        class Meta(ModelResource.Meta):
                default_filters = {
                        'name__startswith': 'lamp'
                }

The default filters will eventually be applied to the queryset during the apply_filters method, resulting in something like this:

filtered_instances = Foo.objects.filter(name__startswith='lamp')

Client Side Filtering with Get Params

API consumers often need to be able to filter against certain resource fields using GET parameters. Filtering is enabled by specifying the allowed_filters array. The array takes a series of Queryset filter keywords:

class FooResource(ModelResource):
        class Meta(ModelResource.Meta):
                allowed_filters = [
                        'name__icontains',
                        'created__lte',
                        'created__gte',
                        'bar__name'
                ]

In the above example, API consumers will be allowed to get Foo objects by searching for strings in the Foo name, or by finding Foos created before or after a given datetime.

Note

Each Queryset filter has to be specified using the entire filter name. While verbose, this allows custom or related field parameters such as bar__name to be easily specified.

Ordering Results

If you want to specify the default order for objected, returned, you can simply specify the order_by string using the default_ordering Meta field:

class FooResource(ModelResource):
        class Meta(ModelResource.Meta):
                default_ordering='-created'

The value of default_ordering should be the same one you would use when performing order_by on a queryset. The above example will result in the following operation:

Foo.objects.order_by('-created')

To allow API consumers to order the results, the allowed_ordering field is an array of valid ordering keys:

class FooResource(ModelResource):
        class Meta(ModelResource.Meta):
                allowed_ordering = [
                        'created',
                        '-created'
                ]

Note how the forward and reverse string both have to be specified. This is to provide precise control over client ordering values.

How Filters & Ordering are Applied

Filtering and ordering happens inside two steps in the default conduit pipeline. The first happens inside process_filters. To determine order, first the method looks for an order_by GET parameter. If none are specified, it defaults to the default_ordering attribute. If the order_by parameter is not a valid value, the client receives a 400.

The filters start with the default_filters dictionary. This dictionary is then updated from filters specified in the GET parameters, provided they are specified in allowed_filters.

After the order_by and filters are determined, their values are sent forward in the kwargs dictionary where they are picked up again in pre_get_list. This is the method that first applies the kwargs['order_by'] value, and then applies the values inside kwargs['filters']. It stores the ordered and filtered queryset inside of kwargs['objs']. The objects are then subject to authorization limits and paginated inside get_list before the final set of objects is determined.