【问题标题】:Python Django "and/or" searching in databasePython Django“和/或”在数据库中搜索
【发布时间】:2026-01-07 05:25:08
【问题描述】:

我设置了一个数据库,并且我希望设置搜索引擎,以便它在搜索输入到不同搜索字段中的所有内容时忽略空字段。现在我正在使用 AND 语句(“,”)和 OR 语句(“|”)的组合,但我不确定如何编写它来忽略空复选框和文本值,但只搜索填充的复选框和文本我的views.py中的搜索代码是:

incidents = Incident.objects.filter(
                                        Q(datepicker__range=[date_start, date_end]), 
                                        Q(country__contains=country), 
                                        Q(city__contains=city) 
                                        | Q(state__contains=state) 
                                        | Q(province__contains=province) 
                                        | Q(used_firearm__contains=firearm)
                                        | Q(used_taser__contains=taser)
                                        | Q(used_teargas__contains=teargas)
                                        | Q(victim_1_name__contains=victim_name)
                                        | Q(victim_1_ethnicity__contains=victim_ethnicity)
                                        | Q(victim_1_age__contains=victim_age)
                                        | Q(victim_1_sex__contains=victim_sex)
                                        | Q(victim_1_status__contains=victim_status)
                                        | Q(victim_1_armed__contains=victim_armed)
                                        )

需要日期选择器范围和国家/地区,然后其他所有内容都是 OR 语句。例如,如果国家是美国,那么我希望它按州搜索,但如果国家是加拿大,我希望它按省搜索。如果两者都没有填写,我希望它忽略两者。

例如,现在,如果我选择开始日期和结束日期,将国家/地区设为 USA 并选择受害者_1_name,它将只返回日期范围内的所有内容,而不管名称如何。在对已填写的字段使用 AND 连接器时,如何让它忽略空白字段?

此外,“used_firearm”和“used_taser”之类的东西是复选框,我用于读取这些字段的views.py是:

if request.POST.get('used_teargas', False):
                teargas             = request.POST['used_teargas']

如果它是空的,它是否足以让它忽略复选框,而如果它被选中则传递一个“True”值?

【问题讨论】:

  • 你应该考虑使用合适的搜索引擎,比如solr
  • 在将搜索选项传递给过滤器对象之前在列表中构建您的搜索选项,以便您只应用设置的选项。

标签: python django search checkbox


【解决方案1】:

可能是这样的:

text_fields = {
    'city': request.POST.get('city'),
    'state': request.POST.get('state'),
    'province': request.POST.get('province'),
    'used_teargas': request.POST.get('teargas'),
    'victim_1_name': request.POST.get('victim_name'),
    'victim_1_ethnicity': request.POST.get('victim_ethnicity'),
    'victim_1_age': request.POST.get('victim_age'),
    'victim_1_sex': request.POST.get('victim_sex'),
    'victim_1_status': request.POST.get('victim_status'),
}

boolean_fields = {
    'used_taser': request.POST.get('taser'),
    'used_teargas': request.POST.get('teargas'),
    'victim_1_armed': request.POST.get('victim_armed')
}

q_objects = Q()

for field, value in text_fields.iteritems():
    if value:
        q_objects |= Q(**{field+'__contains': value})

for field, value in boolean_fields.iteritems():
    if value:
        q_objects |= Q(**{field: True})

incidents = Incident.objects.filter(
    Q(datepicker__range=[date_start, date_end]), 
    Q(country__contains=country), 
    q_objects
)

生成的查询与您提供的查询非常相似,唯一的区别是列表或 ored (|) Q 对象(此处命名为 q_objects)是动态构建的 - 这允许您提供了特定字段是否应包含在该列表中的规则(在该特定情况下为“if value”。这将完全符合您的要求 - 过滤掉空字符串、False 值和None 值)。

您还应该研究专门的搜索解决方案,例如 Haystack

【讨论】:

  • 感谢您的帮助!这比我写的要短得多。我确实计划研究 Haystack 和 Solr 搜索插件,我只是想自己写一些东西,以便了解它们是如何工作的。不过,有一个问题 - 这适用于除我的复选框之外的所有内容。我在模型中将它们设置为 BooleanFields,但是当我在搜索字段中选择一个时,它没有任何效果。不过,所有其他搜索字段都可以使用。我是否需要告诉它为复选框寻找不同的值?
  • 我添加了一个使用bool() 的示例,以确保您获得一个合乎逻辑的值。
  • 嗯,我很困惑,它仍然无法正常工作。 bool(request.POST.get('victim_armed')) 会返回一个我想在 Q(**{field+'__contains': value}) 中使用的值,还是我想使用类似 Q(** {field+'__isnull': 值}) ?当我检查我的 sqlite 数据库时,它告诉我复选框值保存为 0 或 1,但是当我将 {{incident.victim_armed}} 放入模板中时,它会打印 True 或 False。我应该使用单独的 Q 搜索复选框还是我的模型有更深层次的问题?复选框 HTML 是
  • 检查一下,它看起来可能是数据库模型的问题。我的 models.py 有victim_armed = models.BooleanField() ,我的事件创建页面有 {{form.victim_armed}} 作为复选框创建者。我发送的唯一值是 'on' 或 null。我是否应该将模型更改为victim_armed = models.BooleanField(default=False) 以确保该列中有数据以便可搜索?还是我只是为复选框使用了错误的搜索词?将值添加到复选框 HTML 可以解决此问题吗?或者在views.py中添加一个值?
  • 我们不能将__contains 用于布尔字段。我更新了帖子。