# Am I dynamic filtering correctly in Django?

I needed a way to get URL parameters and put them and their values into a query set's .filter() if they exist. After a day of piecing together information from the Interwebs, I have a working solution to my problem. However, is it the best way to do this? I feel it can be improved or streamlined, but my tiny brain is failing me:

In utilities.py:

def get_filters(url, allowed):
query = parse.urlsplit(url).query
pack = dict(parse.parse_qsl(query))
translated = {}

for pk, pv in pack.items():
for ak, av in allowed.items():
if pk == ak:
translated[av] = pv

return translated


In views.py:

from utilities import get_filters

people = Person.objects.all()
url = request.get_full_path()

allowed_filters = {
'location': 'person_location',
'role': 'person_role',
}

filters = get_filters(url, allowed_filters)

if filters:
filtered_query = people.filter(**filters)
else:
filtered_query = people

if ('search' in request.GET) and request.GET['search'].strip():
query_string = request.GET['search']
query_search = get_query(query_string, ['person_first_name', 'person_last_name'])
query_results = filtered_query.filter(query_search)
else:
query_results = filtered_query


It does everything I need it to: if a URL parameter is in the allowed list, it takes that parameter and value, packs it into a dictionary, and shoves it into filter() to be unpacked by the interpreter.

This way whenever I want to add a new filter, I just add it in the allowed list and I don't have to touch anything else. I did it this way so I could use an alias like special_id=3 in the URL to target a relationship like person__special__special_id=3 without the URL getting cluttered like the Django admin side does.

Any suggestions for improving this?

• my tiny brain is failing me switch to one of the others. May 13 '20 at 11:09
• Heterogeneous multi-processing (global task scheduling) would be huge benefit, for sure! May 13 '20 at 19:07

You can change the first method to

def get_filters(url, allowed):
query = parse.urlsplit(url).query
pack = dict(parse.parse_qsl(query))
translated = {}

for pk, pv in pack.items():
if pk in allowed:
translated[allowed[pk]] = pv

return translated


Remove this condition, it's useless.

if filters:
filtered_query = people.filter(**filters)
else:
filtered_query = people


and just use

filtered_query = people.filter(**filters)


Maybe add search to the allowed filters? and improve the method to handle multiple values for a specific key.

allowed_filters = {
'location': 'person_location',
'role': 'person_role',
'search': ['person_first_name', 'person_last_name']
}

$$$$
`