【问题标题】:Django query : Request with startswith in an arrayDjango查询:在数组中使用startswith请求
【发布时间】:2019-05-15 19:35:36
【问题描述】:

这是我的代码:

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_ 作为reducer,这意味着您说:邮政编码应以78 开头,并且应以10 开头。任何文本不能同时以两者开头。

标签: python django django-queryset


【解决方案1】:

这里的主要问题是您使用and_ 作为reduce 运算符,这意味着您指定code_postal 应同时以7895 开头的条件。任何文本/数字都不能同时以7895(以及所有其他值)开头。

您可以通过使用or_ 减少此问题来轻松解决此问题:

from operator import or_

query = reduce(or_, (Q(code_postal__startswith=item) for item in q))
result = Record14.objects.filter(query)

话虽如此,在这里使用regular expression [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)

^ 是此处的起始锚点,管道充当“联合”,因此此正则表达式查找以 789577 等开头的列。

【讨论】:

    【解决方案2】:

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

    简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 2021-08-28
      • 2010-12-03
      • 2017-02-13
      • 2011-05-22
      相关资源
      最近更新 更多