[英]Django - filtering queryset with optional FormFields
假设我有一个模型:
class House(models.Model):
(...)
price = models.DecimalField(decimal_places=2, max_digits=8)
area = models.DecimalField(decimal_places=2, max_digits=6)
我有一个搜索房屋的表格:
class SearchHouseForm(forms.Form):
price_min = forms.DecimalField(required=False, initial=0, decimal_places=2, max_digits=8)
price_max = forms.DecimalField(required=False, initial=999999, decimal_places=2, max_digits=6)
和视图功能:
def search_for_houses(request):
queryset = House.objects.all()
if request.method == 'GET' and 'search-submit-button' in request.GET:
form = SearchHouseForm(request.GET)
if form.is_valid():
queryset = queryset.filter(
price__lte = form.cleaned_data['price_max'],
price__gte = form.cleaned_data['price_min']
)
else:
(...)
return render(request, template, {'house_list': queryset, 'form': form})
我对.filter()
有.filter()
。 我希望仅当用户在表单字段中提供任何值时才应用过滤器。 如果price_max
字段留为空白,则仅应应用price__gte = form.cleaned_data['price_min']
。 如果price_max
和price_min
都留为空白,则应返回所有House
对象。 当前我得到ValueError Cannot use None as a query value
有没有一种干净的方法可以做到这一点? 我唯一能想到的是所有此类可选字段的一串if
语句:
if form.cleaned_data['price_max'] is not None:
queryset = queryset.filter((...))
if form.cleaned_data['price_min'] is not None:
queryset = queryset.filter((...))
(...)
这似乎不是一个好主意,特别是如果我想应用大量这样的可选过滤字段时。
在只有两个过滤器的情况下,我将按照您的建议继续进行,仅使用if ...
条件。
但是,如果您将来希望构建更复杂的查询,请考虑使用Q
对象。 有一个很好的博客文章在这里显示了一些例子。 例如,您可以创建一个过滤器字典,并遍历您的字段,如果该字段的值已填充,则添加Q过滤器。
朝着这个方向前进:
queries = {'price_max': "price__lte", 'price_min': "price__gte"}
predicates = []
for field, value in cleaned_data.items():
if value and field in queries:
predicates.append((queries[field], value))
q_list = [Q(x) for x in predicates]
queryset = queryset.filter(reduce(operator.and_, q_list))
不太确定,还有其他方法可以做到。
if form.cleaned_data['price_max']:
#filtering
if form.cleaned_data['price_min']:
#filtering
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.