Django обновить фильтр /prefetch_related изменение поведения?
Я нахожусь в процессе обновления с Django 1.8.19 до 1.11.15, и я нашел кусок кода, который ломается.
В частности, этот запрос делает что-то отличное от того, что он делал раньше.
project_groups = brand.project_groups.prefetch_related(
'project', 'project__score', 'project__themes').filter(
project=projects
).distinct()
Ранее (в Django 1.8), согласно выводу "project_groups.query", он создавал SQL, в том числе:
... projectgroup.project_id IN [projects query]
Теперь он производит чтение SQL:
... projectgroup.project_id = [projects query]
Это прерывается, поскольку [проектный запрос] возвращает более одной строки. Итак, я получаю:
ProgrammingError: more than one row returned by a subquery used as an expression
Единственные изменения, которые я внес в код для этого обновления, касаются моделей и миграций для использования ArrayField и HStoreField из django.contrib.postgres.fields вместо django_hstore эквивалентов.
Я предполагаю, что оригинальный код был неправильным, но работал из-за ошибки в Django (filter/prefetch_related), которая теперь была исправлена. Это может быть правильно? Если это на самом деле новая ошибка в Django, я не хочу писать код, который опирается на это!
1 ответ
Произошло изменение в поведении Django при поиске в поле между 1.8 и 1.9, что объясняет это - вы можете увидеть детали в билете Django № 25284.
В Django 1.8 такой запрос, как Model.objects.filter(related_id = RelatedModel.objects.all())
раньше приводил к неявному поиску __in, поэтому SQL-запрос содержал related_id IN (SELECT id FROM ...)
, Но в Django 1.9 "IN" изменяется на "=", что приводит к разрыву запроса в MySql и Postgres. Изменение было классифицировано как исправление ошибки, поскольку неявное поведение "IN" было недокументированным и, вероятно, случайным.
Вы должны иметь возможность довольно легко исправить запрос, добавив явный тип поиска к полевому поиску, такой как .filter(project__in=projects)
- см. документацию Django: полевые поиски