pythondjangodjango-rest-frameworkdjango-filterdjango-q

Django Filters: Suggest improvements to dynamic filtering logic


I am performing filtration on my dataset based on many kinds of search criterias selected by users on the frontend. Here are a few considerations:

Here is how the form looks: my form

This is my current approach:

class BookingExportFilterBackend(generic_filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        predicate = request.data

        if all(dt in predicate for dt in ('from_date', 'to_date')):
            queryset = queryset.filter(date__range=(predicate['from_date'], predicate['to_date']))

        if 'from_date' in predicate and 'to_date' not in predicate:
            queryset = queryset.filter(date__gte=predicate['from_date'])

        if 'to_date' in predicate and 'from_date' not in predicate:
            queryset = queryset.filter(date__lte=predicate['to_date'])

        if 'state' in predicate:
            queryset = queryset.filter(state__in=predicate['state'])

        if 'clients' in predicate:
            queryset = queryset.filter(client__in=predicate['clients'])

        if 'camera_operators' in predicate:
            queryset = queryset.filter(camera_operator__uuid__in=predicate['camera_operators'])

        return queryset

I feel that it can be improved, especially the date part. I am using the Q library as well but I'm pretty new to Django. (PS: I've come from Java/Spring/Hibernate background).

Please help improve the code.


Solution

  • You should try the django-filters lib for filtering. It is quite simple to use and provides a range of filtering options.

    For your case, you could start with something like this: Note: please do not use date as a field/variable name, I have replaced with booking_date in the example below.

    class BookingFilter(django_filters.FilterSet):
        from_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='gt')
        to_date = django_filters.NumberFilter(field_name='booking_date', lookup_expr='lt')
    
        status = django_filters.CharFilter(name="status", lookup_type="contains"
    
        class Meta:
            model = Booking # replace with your appropriate Model