Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I dynamically set Django filter in queryset

I am doing a table in React, fetching some data from my Django DB.
It has filters and I want them to call the API to get results if needed.

Thing is I have to duplicate a lot of lines whereas I am pretty sure there is a better way to do this.

Here is some part of the code:

        if ss_value and not es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value)
        elif not ss_value and es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_arrival=es_value)
        elif not ss_value and not es_value and iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(is_virtual=iv_value)
        elif not ss_value and not es_value and not iv_value and timestamp:
            queryset = DailyReport.objects.all().filter(
                Q(timestamp__range=(min_dt, max_dt)) | Q(upload_timestamp__range=(min_dt, max_dt)))
            logger.debug(queryset)
        elif ss_value and es_value and not iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value, station_arrival=es_value)
        elif ss_value and not es_value and iv_value and not timestamp:
            queryset = DailyReport.objects.all().filter(station_departure=ss_value, is_virtual=iv_value)

and it goes on and on.

Do you have any idea of a way to do it in a cleaner way ??

Thank you :)

like image 581
Kimor Avatar asked Sep 16 '25 03:09

Kimor


1 Answers

The technique you're missing has less to do with django and more to do with Python in general.

def myfunc1(arg1, arg2):
    print(arg1, arg2)

def myfunc2(arg1=None, arg2=None):
    print(arg1, arg2)

mylist = ['val1', 'val2']
mydict = {'arg1': 'val1', 'arg2': 'val2'}

Assuming you have the above:

myfunc1('val1', 'val2')
myfunc1(*mylist)

Are equivalent! Similarly:

myfunc2('val1', 'val2')
myfunc2(**mydict)

Are also equivalent!

You can pass a list into a function call as if they're the positional arguments with a single *, and you can pass a dictionary as keyword arguments with a double *

So ultimately what you want to do is build up a dictionary of things of the form:

filter_kwargs = {
   'django_filter_kwarg_name': 'django_filter_value'
}

So for you this might be:

# build up the dictionary (or maybe you can do this off the form, request.GET, etc
filter_kwargs = {
    'station_departure': ss_value,
    'station_arrival': es_value,
    ....
}
# do something here to filter out the empty/None key/values
filter_kwargs = {key: value if value for key, value in filter_kwargs.items}
# now get the queryset
queryset = DailyReport.objects.all().filter(**filter_kwargs)


like image 121
Mike Sandford Avatar answered Sep 18 '25 17:09

Mike Sandford