Django查询:在数组中使用startswith进行请求

问题描述 投票:0回答:2

这是我的代码:

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 数组中的值开头。

我确信我的数据库中有数据,但查询是空的......

我不明白为什么。

python django django-queryset
2个回答
6
投票

这里的主要问题是您使用

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
等开头的列


3
投票

您还可以(自 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
)

简单。

© www.soinside.com 2019 - 2024. All rights reserved.