Запрос Django: запрос с начальными значениями в массиве - PullRequest
1 голос
/ 15 мая 2019

вот мой код:

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.

У меня есть данные вмоя база данных, я уверен, но запрос пуст ...

Я не понимаю, почему.

Ответы [ 2 ]

2 голосов
/ 15 мая 2019

Основная проблема здесь заключается в том, что вы используете and_ как оператор уменьшения, так что это означает, что вы указываете в качестве условия, что code_postal должен начинаться с 78 и 95 одновременно.Никакой текст / число не может начинаться с 78 и 95 (и всех других значений) одновременно.

Вы можете легко исправить это, уменьшив значение с помощью or_:

from operator import <b>or_</b>

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

При этом, вероятно, лучше использовать регулярное выражение [wiki] здесь, например:

from re import escape as <b>reescape</b>

result = Record14.objects.filter(
    code_postal<b>__regex= '^({})'.format('|'.join(map(reescape, q)))</b>
)

Для заданного вами списка q, это приведет к регулярному выражению:

^(78|95|77|91|92|93|94|75|27|28|45|89|10|51|02|60|27)

Здесь ^ является начальным якорем, а канал действует как «объединение», поэтому это регулярное выражение ищет столбцы, начинающиеся с 78, 95, 77 и т. Д.

1 голос
/ 16 мая 2019

Вы также можете (начиная с 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
)

простой.

...