繁体   English   中英

Django-使用可选的FormFields过滤queryset

[英]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_maxprice_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM