Reputation:
In my app, I have a form. Depending of the form, one or many filters could be configured by the user.
In my view, I have for exemple :
query = Test.objects.filter(filter1 = request.post['filter1'], filter2 = request.post['filter2'], filter3 = request.post['filter3'])
So, sometimes filter1, filter2 or filter3 could not exist.
If any filters doesn't exist, I just want to ignore the filter.
I could do a script with many "IF" conditions but may be there is a smart solution ?
Thanks for your help !
Upvotes: 6
Views: 11711
Reputation: 139
You could use something like this:
import ast
def query_to_dict(query) -> dict:
filters = {}
for field, value in query.items(): # <- param and value like ?param1=True
filters[field] = ast.literal_eval(str(value)) # <- parse list/str/bool
return filters
def event_view(request):
events = Event.objects.filter(
Q(**query_to_dict(request.GET))
)
return Response(
EventsSerializer(events, many=True).data
)
In this example:
ast
- module which will help to parse bool values and lists
request.GET
- this is your query params ?param1=True¶m2="[1, 2]"
. Make sure to pass params in way like ?title="hello"
- using double quotes
query_to_dict
- function which will convert query params to python dict. So you can pass this dict to your Event.objects.filter
.
Benefit of using filtering this way, you can pass ?id__in="[1, 2]"
something like this and it will work. I can't say for sure how it secure or not, but for some complex filtering or bool fields filtering it is perfect.
Upvotes: 0
Reputation: 19
This code solved my problem:
if request.method == 'GET':
filters = {}
for key, value in request.GET.items():
if value != '':
filters[key] = value
filter_list=Pet.objects.filter(**filters)
Upvotes: 2
Reputation: 4155
You could do something along the lines of:
filters = {}
for key, value in request.post.items():
if key in ['filter1', 'filter2', 'filter3']:
filters[key] = value
Test.objects.filter(**filters)
Where the list is a list of keys that you are intending to filter by
Edit
As Thomas Junk suggested you can make it a lot cleaner with a comprehension:
filters = {
key: value
for key, value in request.post.items()
if key in ['filter1', 'filter2', 'filter3']
}
Test.objects.filter(**filters)
Upvotes: 22