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. \$\endgroup\$