这是我的代码:
q = [
"78",
"95",
"77",
"91",
"92",
"93",
"94",
"75",
"27",
"28",
"45",
"89",
"10",
"51",
"02",
"60",
"27",
]
query = reduce(operator.and_, (Q(code_postal__startswith=item) for item in q))
result = Record14.objects.filter(query)
for r in result :
print(r)
我想要一个包含 Record14 中所有对象的查询,其中 code_postal 以 q 数组中的值开头。
我确信我的数据库中有数据,但查询是空的......
我不明白为什么。
这里的主要问题是您使用
and_
作为归约运算符,这意味着您指定 code_postal
应同时以 78
和 95
开头。任何文本/数字都不能同时以 78
和 95
(以及所有其他值)开头。
您可以通过使用
or_
: 减少此问题来轻松解决此问题
from functools import reduce
from operator import or_
query = reduce(or_, (Q(code_postal__startswith=item) for item in q))
result = Record14.objects.filter(query)
话虽如此,最好在这里使用 正则表达式 [wiki],例如:
from re import escape as reescape
result = Record14.objects.filter(
code_postal__regex= '^({})'.format('|'.join(map(reescape, q)))
)
对于您给定的列表
q
,这将产生一个正则表达式:
^(78|95|77|91|92|93|94|75|27|28|45|89|10|51|02|60|27)
^
是这里的起始锚点,管道充当“联合”,因此该正则表达式查找以78
、95
、77
等开头的列
您还可以(自 Django 2.1 起)将注释与名为 Left 的数据库函数结合起来,并使用
__in
查找:
from django.db.models.functions import Left
records = Record14.objects.annotate(
code_postal_ini=Left('code_postal', 2) # Take the 2 first characters of code_postal
).filter(
code_postal_ini__in=q # Filter if those 2 first chars are contained in q
)
简单。