Django 6.1.1 был выпущен 2 сентября 2026 года. Обновление устранило 12 ошибок, преимущественно связанных с регрессиями ветки 6.1. Изменения затронули ORM, Django Admin, миграции, шаблоны, формы и SQLite. Для проектов на Django 6.1 это обновление особенно важно при работе с несколькими базами данных, использовании Prefetch, кастомном Model.from_db() и сложных запросах.

Django 6.1.1 сосредоточен на исправлении регрессий
Django 6.1.1 — первый корректирующий релиз после выхода Django 6.1 от 5 августа 2026 года. Согласно официальным release notes, новая версия исправляет один сбой, присутствовавший начиная с Django 5.2, и ряд ошибок, обнаруженных в Django 6.1.
Новых возможностей в 6.1.1 нет. Это именно patch-релиз, задача которого — стабилизировать изменения Django 6.1 после первого месяца эксплуатации в реальных проектах.
Наиболее заметная группа исправлений связана с ORM. Несколько ошибок могли приводить не просто к исключениям, а к неправильному результату запроса, обращению к другой базе данных или потере выбранных аннотаций.
Всего в release notes перечислено 12 исправлений:
| Область | Что исправлено | Практический эффект |
| ORM | distinct(*fields) вместе с order_by() и values() больше не падает при двух lookup-путях к одной колонке | Сложные запросы снова выполняются корректно |
| Templates | Строковые и переводимые литералы с .. больше не попадают под проверку устаревших double-dot lookup | Шаблоны вроде {{ "a..b" }} не вызывают ложную ошибку |
| Django Admin | ModelAdmin.list_display с несколькими переходами через __ больше не падает и не берет значение не с той модели | Исправлено отображение связанных полей в списках админки |
| Models | Проверка fields.E323 теперь обнаруживает смешанные варианты on_delete в автоматически созданных промежуточных моделях ManyToManyField | Ошибочные комбинации обнаруживаются системной проверкой |
| ORM / multi-DB | Кастомный queryset в Prefetch для ForeignKey и обратного OneToOneField снова наследует маршрутизацию базы от родительского queryset | Запросы не уходят ошибочно в default вместо выбранной БД |
| Forms | HTML-safe строки в media-ресурсах снова выводятся как готовая разметка | mark_safe() больше не интерпретируется как путь к статическому файлу |
| Migrations | Изменение только Python-варианта on_delete больше не запускает лишнее изменение схемы | Меньше ненужного DDL и блокировок таблиц |
| SQLite | DecimalField без max_digits и decimal_places больше не вызывает сбой при чтении значения | Исправлен редкий, но реальный сценарий работы с SQLite |
| ORM API | Старые переопределения Model.from_db() без fetch_mode снова работают | Устранен TypeError после перехода на 6.1 |
| Django Admin | Исправлен поиск по search_fields с __exact, choices и BooleanField | Поиск больше не падает и не возвращает ложные совпадения |
| ORM | __in и __range для аннотаций корректно принимают итераторы | Итератор больше не исчерпывается до построения SQL |
| ORM | in_bulk() после values() и values_list() сохраняет выбранные аннотации и корректные ключи | Результат больше не теряет данные из проекции |
ORM получил наиболее существенные исправления
Django 6.1.1 закрывает сразу несколько регрессий ORM, способных влиять на корректность данных, а не только на стабильность приложения. На практике это самая важная часть релиза для backend-разработчиков.
Prefetch снова корректно работает с несколькими базами
Одна из наиболее неприятных регрессий Django 6.1 проявлялась при использовании Prefetch с кастомным queryset для прямого ForeignKey или обратного OneToOneField.
Если основной queryset выполнялся через конкретный alias базы данных, например replica, связанный кастомный queryset мог потерять этот контекст и обратиться к default. В тикете #37300 показан сценарий, где основной объект загружается из replica, а связанный объект — уже из default.
Это могло привести к двум вариантам поведения:
- приложение незаметно читало данные не из той базы;
- Django выбрасывал
ValueError, если database router запрещал связывать объекты, полученные из разных БД.
В 6.1.1 подсказка о родительском экземпляре снова передается кастомному queryset, поэтому маршрутизация возвращена к поведению Django 6.0.
Для проектов с primary/replica, шардингом или собственными database routers это одно из главных оснований обновиться без откладывания.
Итераторы в __in и __range больше не теряются
В Django 6.1 появился дефект при передаче итератора в __in или __range, если левая часть lookup была аннотацией или alias.
Проблема заключалась в двойном обходе правой части выражения. Первый проход исчерпывал iterator, после чего второй уже не получал значений. Для __in это могло дать пустой queryset, а __range — завершиться ValueError.
Django 6.1.1 устраняет эту регрессию. Обычные lookup по полям при этом не были затронуты — ошибка относилась именно к пути через annotation или alias.
in_bulk() больше не отбрасывает аннотации
Еще одна ошибка затрагивала новую возможность комбинировать QuerySet.in_bulk() с values() и values_list().
Если queryset содержал аннотацию, а поле, используемое in_bulk() как ключ словаря, отсутствовало в выбранной проекции, Django внутренне перестраивал список полей. При этом выбранные аннотации могли исчезнуть из результата.
После обновления до 6.1.1 in_bulk() сохраняет аннотации и формирует правильные ключи. Это особенно актуально для кода, где ORM используется как слой подготовки компактных словарей или кортежей без создания полных экземпляров моделей.
Исправления Django Admin устраняют сбои и неверные значения
Django 6.1.1 исправляет две регрессии административной панели: работу связанных полей в list_display и поиск через search_fields с точными lookup.
В ModelAdmin.list_display проблема проявлялась при проходе через несколько связей с помощью __. Например, колонка могла ссылаться на поле модели через цепочку отношений второго уровня.
В Django 6.1 такой сценарий мог завершиться ошибкой или, что хуже, показать значение не из той модели, если одинаковое имя поля встречалось на разных уровнях связи. В тикете #37270 этот дефект был классифицирован как release blocker.
Отдельно исправлен поиск в changelist:
search_fieldsс__exactпо полю сchoicesмог приводить к сбою;__exactдляBooleanFieldмог ошибочно сопоставлять любой поисковый термин со всеми строками, где значение равноTrue.
Для внутренних административных интерфейсов это не просто визуальная правка: неверное значение в списке или некорректный поиск способны привести пользователя к неправильному объекту или ошибочному решению.
Model.from_db() получил переходную совместимость
Django 6.1 добавил fetch modes для управления поведением полей, данные которых не были загружены первоначальным запросом. Одновременно в вызов Model.from_db() появился новый keyword-аргумент fetch_mode.
Проблема возникла у моделей, где разработчики переопределяли публичный метод по старой сигнатуре:
@classmethod
def from_db(cls, db, field_names, values):
...После перехода на Django 6.1 любой запрос к такой модели мог завершиться ошибкой:
TypeError: MyModel.from_db() got an unexpected keyword argument 'fetch_mode'Django 6.1.1 восстанавливает совместимость: фреймворк определяет, поддерживает ли пользовательское переопределение fetch_mode, и для старой сигнатуры вызывает метод без нового аргумента.
При этом старый вариант считается устаревающим. В тикете #37259 указано, что Django генерирует RemovedInDjango70Warning, поэтому собственные реализации лучше обновить заранее:
@classmethod
def from_db(cls, db, field_names, values, *, fetch_mode=None):
...Таким образом, 6.1.1 снимает немедленную проблему совместимости, но не отменяет необходимость адаптировать пользовательский код до Django 7.0.
Миграции on_delete снова избегают лишнего DDL
Django 6.1 расширил работу с удалением связанных объектов на уровне базы данных, но изменение затронуло и обычные Python-варианты on_delete.
В результате миграция, меняющая, например, CASCADE на PROTECT, могла выполнять реальную операцию изменения схемы, хотя на уровне БД такая смена не требовала DDL. На большинстве СУБД это означало удаление и повторное создание внешнего ключа, а на SQLite — потенциальную перестройку всей таблицы.
Исправление #37260 возвращает прежнюю логику:
- переход между Python-level вариантами
on_deleteснова является database no-op; - переход к новым database-level вариантам или между ними по-прежнему изменяет схему там, где это требуется.
Для крупных таблиц это существенная разница. Лишний DDL может увеличить время deploy, удерживать блокировки и создавать ненужную нагрузку на production-базу.
SQLite, шаблоны и form media тоже получили исправления
Несколько изменений Django 6.1.1 закрывают более узкие сценарии, но каждый из них способен проявиться в production или тестовом окружении.
DecimalField без явно заданных max_digits и decimal_places больше не приводит к сбою при получении значений из SQLite. Такой сценарий встречается реже стандартной декларации decimal-полей, однако SQLite часто используется локально и в автоматических тестах, поэтому дефект мог ломать CI даже у проектов с другой production-СУБД.
Шаблонизатор перестал ошибочно применять deprecation double-dot lookup к строковым литералам с двумя точками подряд. Конструкция вида:
{{ "a..b" }}снова рассматривается как обычная строка, а не как запрещаемая форма обращения к переменной.
Исправлена и работа form media. HTML-safe строки, созданные, например, через mark_safe(), в Django 6.1 могли ошибочно трактоваться как путь к asset. В 6.1.1 такие значения снова рендерятся непосредственно как безопасная HTML-разметка.
Обновление до Django 6.1.1
Django 6.1.1 опубликован на PyPI 2 сентября 2026 года. Пакет требует Python 3.12 или новее, а ветка Django 6.1 официально поддерживает Python 3.12, 3.13 и 3.14.
Для существующего проекта на Django 6.1 обновление выполняется обычным способом:
python -m pip install --upgrade "Django==6.1.1"На Windows официальный сайт также приводит вариант:
py -m pip install "Django==6.1.1"После обновления имеет смысл прогнать тесты прежде всего для следующих участков:
- queryset с
Prefetch()и несколькими подключениями к БД; - собственные переопределения
Model.from_db(); - Django Admin с цепочками связей в
list_displayи сложнымиsearch_fields; - запросы с annotations/aliases и
__in,__range,in_bulk(); - миграции, меняющие
on_delete; - тесты на SQLite, если в моделях используются нестандартно определенные
DecimalField.
Вывод
Версия Django 6.1.1 не относится к разряду security-релизов: в официальных release notes отсутствуют упоминания CVE или отдельный раздел с исправлением уязвимостей. Основное преимущество этого обновления заключается в устранении регрессий, возникших после перехода на Django 6.1. Некоторые из этих регрессий касались корректности запросов и функционирования баз данных.
Наивысший приоритет обновление имеет для проектов, которые уже используют Django 6.1 и работают с multi-DB, Prefetch, сложным ORM, кастомным Model.from_db() или насыщенной административной панелью. Даже если эти сценарии не используются, оставаться на 6.1.0 особого смысла нет: официальная страница загрузки Django прямо рекомендует переходить на последний patch-релиз соответствующей ветки и указывает Django 6.1.1 как текущую стабильную версию серии 6.1.
При этом обновление не требует освоения новых API. Основная задача после установки — прогнать тестовый набор и обратить внимание на предупреждение для старой сигнатуры Model.from_db(): совместимость восстановлена временно, а пользовательский код следует подготовить к будущему удалению старого варианта в Django 7.0.