我有4个参数:城市,省份,strtype,方向,当该参数不为空时,我想在过滤器中使用它;当它为空时,请勿将其设置为过滤器关键字。
我使用的当前代码部分如下:
if (direction == '') & (strtype == '') & (city == '') & (province == ''):
queryset = address.objects.filter(addline__startswith=keyword)[:10]
if not queryset.exists():
queryset = address.objects.filter(strname__startswith=keyword)[:10]
return queryset
else:
return queryset
if (direction != '') & (strtype == '') & (city == '') & (province == ''):
queryset = address.objects.filter(addline__startswith=keyword,
strdir=direction)[:10]
if not queryset.exists():
queryset = address.objects.filter(strname__startswith=keyword,
strdir=direction)[:10]
return queryset
else:
return queryset
有16种可能性,这意味着我需要写16条if语句!这是太多的代码且不适合使用,有没有简洁的解决方案?
答案 0 :(得分:7)
您可以构建字典,然后使用双星语法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 :(得分:1)
有16种可能性,这意味着我需要写16条if语句!
否!,如果这些参数或多或少地独立发挥作用,则不会。例如,我们可以先提取抽象的通用逻辑:
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
(可能需要一些改动)
所以现在我们可以像这样使用这种逻辑:
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
因此,我们仅需要四个if
案例,并且我们将此功能重复用于两次尝试方法。
由于过滤(如果不是真实性为True)是常见的模式,因此我们可以将其封装在辅助函数中:
def filter_if_truthfull(qs, **kwargs):
retrurn qs.filter(**{k: v for k, v in kwargs.items() if v})
然后我们可以像这样使用它:
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
这允许我们添加任意数量的 named 过滤条件,这些条件仅在值具有真实性true的情况下才适用(对于字符串,如果字符串不为空,则为true,否则为true) None
,它不是字符串,但也不会考虑使用这些过滤器。
如果仍然要使用QuerySet
的结果,最好检查if queryset
,因为这将执行查询,并将元素也加载到queryset中,而.exists()
将使用EXISTS
查询,如果您以后要处理这些元素,则需要执行额外的查询以将其提取到内存中。