Skip to content

Instantly share code, notes, and snippets.

@radupotop
Forked from mlalic/filter_model_mixin.py
Created August 24, 2021 20:12
Show Gist options
  • Save radupotop/a63035ce37b6235716429909b2d3e450 to your computer and use it in GitHub Desktop.
Save radupotop/a63035ce37b6235716429909b2d3e450 to your computer and use it in GitHub Desktop.
A mixin for ``django-rest-framework``providing the possibility to filter the queryset based on query parameters.
from django.db.models import fields as django_fields
class FilteredModelViewSetMixin(object):
"""
A mixin providing the possibility to filter the queryset based on
query parameters.
The mixin overrides the ``get_queryset`` method to return the original
queryset additionally filtered based on the query string parameters.
The filtering is performed by doing a test for direct equality with the
query parameter for all field types except the BooleanField where the
received value is parsed into a ``bool`` instance based on its string
representation ("true" or "false", case insensitive).
Classes mixing-in the Mixin should provide the ``filter_fields``
property to provide a list of fields for which filtering should
be supported.
"""
filter_fields = None
def get_queryset(self):
qs = super(FilteredModelViewSetMixin, self).get_queryset()
if self.filter_fields is None:
return qs
for filter_field_name in self.filter_fields:
if filter_field_name in self.request.QUERY_PARAMS:
filter_value = self.request.QUERY_PARAMS[filter_field_name]
# Special casing the value which is passed to the QS
# filter method for certain types of fields
field = self.model._meta.get_field(filter_field_name)
if isinstance(field, django_fields.BooleanField):
filter_value = filter_value.lower()
if filter_value not in ('true', 'false'):
# Ignore the filter if the value is invalid
continue
filter_value = filter_value.lower() == 'true'
qs = qs.filter(**{
filter_field_name: filter_value,
})
return qs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment