Django通过多个键搜索对象

时间:2014-04-09 18:34:39

标签: django django-models django-queryset django-orm

我正在尝试准备搜索表单,用户可以在其中输入1,2或全部(在本例中为3个)搜索过滤器。

让我们说搜索过滤器是: 姓氏,电话和地址。我试图通过以下方式过滤queryset:

if filterForm.is_valid():
    last_name = filterForm.cleaned_data.get('last_name')
    phone= filterForm.cleaned_data.get('phone')
    address = filterForm.cleaned_data.get('address')

    if last_name is None and phone is None and address is None:
        pass
        #we dont do search id db
    else:
        clients = Client.objects.filter(Q(last_name__contains=last_name) | Q(phone=phone) | Q(address__contains=address))

每个搜索键可能都是空白。

不幸的是,它会返回比预期更多的结果。当我输入搜索过滤器"示例"作为姓氏字段,它返回具有此姓氏+许多其他行的所有字段。

知道如何修复此搜索问题吗?

1 个答案:

答案 0 :(得分:1)

我认为当任何搜索键为空时,搜索会返回比预期更多的结果,因为空白键会匹配任何带有值的行。

只过滤包含值的键,它应该更好。

以下是如何完成的一个例子:

if filterForm.is_valid():
    last_name = filterForm.cleaned_data.get('last_name')
    phone= filterForm.cleaned_data.get('phone')
    address = filterForm.cleaned_data.get('address')

    import operator

    predicates = []

    if last_name:
        predicates.append(Q(last_name__contains=last_name))
    if phone:
        predicates.append(Q(phone=phone))
    if address:
        predicates.append(Q(address__contains=address))

    if len(predicates) == 0:
        # Nothing to search for
        pass
    else:
        clients = Client.objects.filter(reduce(operator.or_, predicates))

上面的代码将动态添加应添加到查询中的过滤器。 oprator.or_的用法将语句与OR连接起来(=至少需要满足一个语句)。如果您希望满足所有陈述,则可以使用operator.and_代替。