Запрос Django: запрос с startwith в массиве

вот мой код:

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_ в качестве редуктора, так что это означает, что вы говорите: что почтовый индекс должен начинаться с 78 и должен начинаться с 10. Текст не может начинаться с обоих одновременно.

Willem Van Onsem 15.05.2019 21:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
1
1 304
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

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

from operator import or_

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

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

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) объединить аннотацию с функцией базы данных с именем Осталось и использовать поиск __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
)

просто.

Другие вопросы по теме