7๐
You can build a dictionary and then pass it as keyword parameters using the double-star syntax f(**kwargs)
:
conds = {}
if direction != '': conds["strdir"] = direction
if strtype != '': conds["strtype"] = strtype
if province != '': conds["province"] = province
if city != '': conds["city"] = city
queryset = address.objects.filter(addline__startswith=keyword,
**conds)[:10]
if not queryset.exists():
queryset = address.objects.filter(strname__startswith=keyword,
**conds)[:10]
1๐
There are 16 posibilities, it means i need to write 16 if statements!
No!, not if these parameters act more or less independent. We can for example first abstract common logic away:
def add_custom_filters(qs, direction, strtype, city, province):
if direction:
qs = qs.filter(strdir=direction)
if strtype:
qs = qs.filter(strype=strtype)
if city:
qs = qs.filter(strcity=city)
if privince:
qs = qs.filter(strprov=privince)
return qs
(might need some altering)
So now we can use this logic like:
queryset = address.objects.filter(addline__startswith=keyword)
queryset = add_custom_filters(queryset, direction, strtype, city, province)[:10]
if not queryset:
queryset = address.objects.filter(strname__startswith=keyword)
queryset = add_custom_filters(queryset, direction, strtype, city, province)[:10]
return queryset
We thus only need four if
cases, and we reuse this function for the two-attempt approach.
Since filtering if not truthiness is True is a common pattern, we can encapsulate this in a helper function:
def filter_if_truthfull(qs, **kwargs):
retrurn qs.filter(**{k: v for k, v in kwargs.items() if v})
then we can use it like:
queryset = address.objects.filter(addline__startswith=keyword)
queryset = filter_if_truthfull(queryset, strdir=direction, strtype=strtype, strcity=city, strprov=province)[:10]
if not queryset:
queryset = address.objects.filter(strname__startswith=keyword)
queryset = filter_if_truthfull(queryset, strdir=direction, strtype=strtype, strcity=city, strprov=province)[:10]
return queryset
This allows us to add an arbitrary amount of named filter criteria that are only applied in case the value has truthiness true (for a string, this happens if the string not empty, in case it is None
, it is not a string, but these filters are also not considered).
In case you are going to use the results of a QuerySet
anyway, it is better to check if queryset
, since this will perform a query, that loads the elements into the queryset as well, whereas .exists()
will query with an EXISTS
query, and if you want to process the elements later, you need to perform an extra query to fetch them in memory.
- [Django]-Django Heroku not serving static files when Debug=False
- [Django]-Can I serve one django app from 2 different apache vhosts?
- [Django]-Django & GDAL โ Could not find the GDAL library
- [Django]-Is there a reason I should be dissuaded from using an alternative templating engine in my Django app?