Примечания к выпуску Django 1.6¶
Примечание
Посвящается Малкольму Трединнику
17 марта 2013 года проект Django и сообщество свободного программного обеспечения потеряли очень дорогого друга и разработчика.
Малкольм был давним участником проекта Django, образцовым членом сообщества, блестящим умом и другом. Его вклад в Django - и во многие другие проекты с открытым исходным кодом - практически невозможно перечислить. Многие из основной команды Django получили от него свои первые патчи; его наставничество обогатило нас. Его внимательность, терпение и преданность делу всегда будут вдохновлять нас.
Этот выпуск Django предназначен для Малкольма.
– Разработчики Django
Ноябрь 6, 2013
Добро пожаловать в Django 1.6!
Эти заметки о выпуске охватывают new features, а также некоторые backwards incompatible changes, о которых вы должны знать при переходе с Django 1.5 или более старых версий. Мы также отказались от некоторых функций, которые подробно описаны в our deprecation plan, и begun the deprecation process for some features.
Совместимость с Python¶
Django 1.6, как и Django 1.5, требует Python 2.6.5 или выше. Python 3 также официально поддерживается. Мы настоятельно рекомендуем последний минорный релиз для каждой поддерживаемой серии Python (2.6.X, 2.7.X, 3.2.X и 3.3.X).
Django 1.6 станет последней серией релизов, поддерживающих Python 2.6; начиная с Django 1.7, минимальная поддерживаемая версия Python будет 2.7.
Python 3.4 не поддерживается, но поддержка будет добавлена в Django 1.7.
Что нового в Django 1.6¶
Упрощенные шаблоны проектов и приложений по умолчанию¶
Шаблоны по умолчанию, используемые startproject
и startapp
, были упрощены и модернизированы. admin теперь включен по умолчанию в новых проектах; sites больше не включается. clickjacking prevention теперь включен, а базой данных по умолчанию является SQLite.
Если шаблоны по умолчанию не соответствуют вашим вкусам, вы можете использовать custom project and app templates.
Улучшенное управление транзакциями¶
Управление транзакциями в Django было переработано. Автокоммит на уровне базы данных теперь включен по умолчанию. Это делает управление транзакциями более явным и должно повысить производительность. Существующие API были устаревшими, и были введены новые API, как описано в transaction management docs.
Постоянные соединения с базой данных¶
Django теперь поддерживает повторное использование одного и того же соединения с базой данных для нескольких запросов. Это позволяет избежать накладных расходов на повторное установление соединения в начале каждого запроса. Для обратной совместимости эта функция отключена по умолчанию. Подробности смотрите в Постоянные соединения.
Обнаружение тестов в любом тестовом модуле¶
Django 1.6 поставляется с новым бегунком тестирования, который позволяет более гибко подходить к расположению тестов. Предыдущий бегунок (django.test.simple.DjangoTestSuiteRunner
) находил тесты только в модулях models.py
и tests.py
пакета Python в INSTALLED_APPS
.
Новый бегунок (django.test.runner.DiscoverRunner
) использует возможности обнаружения тестов, встроенные в unittest2
(версия unittest
в стандартной библиотеке Python 2.7+, поставляемая вместе с Django). С помощью функции обнаружения тестов, тесты могут быть расположены в любом модуле, имя которого соответствует шаблону test*.py
.
Кроме того, метки тестов, предоставляемые в ./manage.py test
для назначения конкретных тестов для запуска, теперь должны быть полными точечными путями Python (или путями каталогов), а не псевдопутями applabel.TestCase.test_method_name
. Это позволяет запускать тесты, расположенные в любом месте вашей кодовой базы, а не только в INSTALLED_APPS
. Для получения более подробной информации смотрите Тестирование в Django.
Это изменение обратно несовместимо; см. backwards-incompatibility notes.
Агрегация с учетом часового пояса¶
Поддержка time zones, введенная в Django 1.4, не очень хорошо работала с QuerySet.dates()
: агрегация всегда выполнялась в UTC. Это ограничение было снято в Django 1.6. Используйте QuerySet.datetimes()
для выполнения агрегации с учетом часового пояса на DateTimeField
.
Поддержка точек сохранения в SQLite¶
В Django 1.6 добавлена поддержка точек сохранения в SQLite, с некоторыми limitations.
BinaryField
поле модели¶
Новое поле модели django.db.models.BinaryField
позволяет хранить в базе данных необработанные двоичные данные.
Виджеты форм GeoDjango¶
GeoDjango теперь предоставляет form fields and widgets для своих гео-специализированных полей. По умолчанию они основаны на OpenLayers, но их можно настроить на использование любого другого JS фреймворка.
check
добавлена команда управления для проверки совместимости¶
Была добавлена команда управления check
, позволяющая проверить, совместима ли ваша текущая конфигурация (в настоящее время ориентированная на настройки) с текущей версией Django.
Model.save()
алгоритм изменен¶
Метод Model.save()
теперь пытается напрямую UPDATE
обратиться к базе данных, если экземпляр имеет значение первичного ключа. Ранее SELECT
выполнялся для определения необходимости UPDATE
или INSERT
. Новый алгоритм требует только одного запроса для обновления существующей строки, в то время как старый алгоритм требовал двух. Более подробную информацию см. в разделе Model.save()
.
В некоторых редких случаях при выполнении триггера UPDATE
база данных не сообщает, что найден совпадающий ряд. Примером может служить триггер PostgreSQL ON UPDATE
, который возвращает NULL
. В таких случаях можно установить флаг django.db.models.Options.select_on_save
, чтобы заставить сохранение использовать старый алгоритм.
Незначительные особенности¶
- Бэкенды аутентификации могут поднять
PermissionDenied
для немедленного отказа в цепочке аутентификации. - Флаг
HttpOnly
может быть установлен на CSRF cookie с помощьюCSRF_COOKIE_HTTPONLY
. assertQuerysetEqual()
теперь проверяет наличие неопределенного порядка и выдаетValueError
, если обнаружен неопределенный порядок. Порядок считается неопределенным, если данныйQuerySet
не является упорядоченным и существует более одного упорядоченного значения для сравнения.- Добавлено
earliest()
для симметрии сlatest()
. - В дополнение к
year
,month
иday
, ORM теперь поддерживает поискhour
,minute
иsecond
. - Django теперь оборачивает все исключения PEP 249.
- Виджеты по умолчанию для
EmailField
,URLField
,IntegerField
,FloatField
иDecimalField
используют новые атрибуты типов, доступные в HTML5 (type='email'
,type='url'
,type='number'
). Обратите внимание, что из-за нестабильной поддержки типа вводаnumber
с локализованными числами в текущих браузерах, Django использует его только тогда, когда числовые поля не локализованы. - Аргумент
number
для lazy plural translations может быть предоставлен во время трансляции, а не во время определения. - Для пользовательских команд управления: Проверка наличия валидных настроек в командах, запрашивающих их с помощью внутренней опции
BaseCommand.can_import_settings
, теперь выполняется независимо от обработки локали, которая должна быть активна во время выполнения команды. На последнюю теперь можно влиять с помощью новой внутренней опцииBaseCommand.leave_locale_alone
. Более подробную информацию смотрите в Команды управления и локали. - Теперь
success_url
изDeletionMixin
интерполируется сobject
из__dict__
. HttpResponseRedirect
иHttpResponsePermanentRedirect
теперь предоставляют атрибутurl
(эквивалент URL, на который будет перенаправлен ответ).- Бэкэнд кэша
MemcachedCache
теперь использует последний доступный протоколpickle
. - Добавлен
SuccessMessageMixin
, который предоставляет атрибутsuccess_message
для классов, основанных наFormView
. - Добавлены опции
django.db.models.ForeignKey.db_constraint
иdjango.db.models.ManyToManyField.db_constraint
. - Библиотека jQuery, встроенная в админку, была обновлена до версии 1.9.1.
- Синдикационные фиды (
django.contrib.syndication
) теперь могут передавать дополнительный контекст шаблонам фидов с помощью нового обратного вызоваFeed.get_context_data()
. - Колонки списка администратора имеют класс
column-<field_name>
в HTML, поэтому заголовок колонок может быть оформлен с помощью CSS, например, для установки ширины колонки. - isolation level может быть настроен под PostgreSQL.
- Тег шаблона
blocktrans
теперь уважаетTEMPLATE_STRING_IF_INVALID
для переменных, не присутствующих в контексте, как и другие конструкции шаблона. SimpleLazyObject
s теперь будет представлять более полезные представления в ситуациях отладки оболочки.- Generic
GeometryField
теперь можно редактировать с помощью виджета OpenLayers в админке. - В документации содержится deployment checklist.
- Команда
diffsettings
приобрела опцию--all
. django.forms.fields.Field.__init__
теперь вызываетsuper()
, что позволяет полевым миксинам реализовывать методы__init__()
, которые будут надежно вызываться.- Параметр
validate_max
был добавлен вBaseFormSet
иformset_factory()
, а также вModelForm
и инлайн-версии. Поведение валидации для наборов форм сmax_num
было уточнено. Ранее недокументированное поведение, которое защищало наборы форм от атак на исчерпание памяти, было задокументировано, а недокументированное ограничение на большее из 1000 илиmax_num
форм было изменено так, чтобы оно всегда было на 1000 больше, чемmax_num
. - Добавлено
BCryptSHA256PasswordHasher
для решения проблемы усечения пароля в bcrypt. - Pillow теперь является предпочтительной библиотекой для работы с изображениями в Django. PIL находится на стадии устаревания (поддержка будет удалена в Django 1.8). Для обновления вам следует начала удалить PIL, потом установить Pillow.
ModelForm
принимает несколько новых опцийMeta
.- Поля, включенные в список
localized_fields
, будут локализованы (путем установкиlocalize
на поле формы). - Опции
labels
,help_texts
иerror_messages
могут быть использованы для настройки полей по умолчанию, подробнее см. в Переопределение полей по умолчанию.
- Поля, включенные в список
- Аргумент
choices
для полей модели теперь принимает итерацию итераций вместо того, чтобы требовать итерацию списков или кортежей. - Фраза причины может быть настроена в ответах HTTP с помощью
reason_phrase
. - При указании URL следующей страницы для
django.contrib.auth.views.logout()
,django.contrib.auth.views.password_reset()
,django.contrib.auth.views.password_reset_confirm()
иdjango.contrib.auth.views.password_change()
теперь можно передавать имена URL, и они будут разрешены. - Новая опция
dumpdata --pks
задает первичные ключи объектов для дампа. Эта опция может использоваться только с одной моделью. - Добавлены методы
QuerySet
first()
иlast()
, которые представляют собой методы удобства, возвращающие первый или последний объект, соответствующий фильтрам. ВозвращаетNone
, если нет ни одного подходящего объекта. View
иRedirectView
теперь поддерживают метод HTTPPATCH
.GenericForeignKey
теперь принимает необязательный аргументfor_concrete_model
, который при установке вFalse
позволяет полю ссылаться на прокси-модели. По умолчанию используется значениеTrue
для сохранения старого поведения.LocaleMiddleware
теперь сохраняет активный язык в сессии, если он там отсутствует. Это предотвращает потерю языковых настроек после удаления сессии, например, выхода из системы.SuspiciousOperation
был дифференцирован на ряд подклассов, и каждый из них будет вести журнал в соответствующий именованный регистратор в иерархии логированияdjango.security
. Наряду с этим изменением, механизмhandler400
и представление по умолчанию используются всякий раз, когдаSuspiciousOperation
достигает обработчика WSGI для возвратаHttpResponseBadRequest
.- Исключение
DoesNotExist
теперь включает сообщение с указанием имени атрибута, используемого для поиска. - Метод
get_or_create()
больше не требует наличия хотя бы одного аргумента в виде ключевого слова. - Класс
SimpleTestCase
включает новый помощник assertion для тестирования ошибок форматирования:assertFormsetError()
. - Список связанных полей, добавленных к
QuerySet
с помощьюselect_related()
, может быть очищен с помощьюselect_related(None)
. - Методы
get_extra()
иget_max_num()
наInlineModelAdmin
могут быть переопределены для настройки дополнительного и максимального количества встроенных форм. - Наборы форм теперь имеют метод
total_error_count()
. ModelForm
поля теперь могут переопределять сообщения об ошибках, определенные в полях модели, используя аргументerror_messages
конструктораField
. Чтобы воспользоваться преимуществами этой новой возможности для ваших пользовательских полей, see the updated recommendation для созданияValidationError
.ModelAdmin
теперь сохраняет фильтры в представлении списка после создания, редактирования или удаления объекта. Можно восстановить прежнее поведение очистки фильтров, установив атрибутpreserve_filters
в значениеFalse
.- Добавлено
FormMixin.get_prefix
(которое по умолчанию возвращаетFormMixin.prefix
) для возможности настройкиprefix
формы. - Необработанные запросы (
Manager.raw()
илиcursor.execute()
) теперь могут использовать стиль параметров «pyformat», при котором заполнители в запросе указываются как'%(name)s'
, а параметры передаются в виде словаря, а не списка (кроме SQLite). Это уже давно возможно (но официально не поддерживается) в MySQL и PostgreSQL, а теперь доступно и в Oracle. - Количество итераций по умолчанию для хешера паролей PBKDF2 было увеличено на 20%. Это обратно совместимое изменение не повлияет на существующие пароли или пользователей, которые подклассифицировали
django.contrib.auth.hashers.PBKDF2PasswordHasher
для изменения значения по умолчанию. Пароли will be upgraded будут использовать новое количество итераций по мере необходимости.
Изменения в 1.6, несовместимые с обратными изменениями¶
Предупреждение
В дополнение к изменениям, описанным в этом разделе, обязательно просмотрите deprecation plan для любых функций, которые были удалены. Если вы не обновили свой код в течение срока устаревания данной функции, ее удаление может выглядеть как изменение, несовместимое с обратным развитием событий.
Новая модель управления транзакциями¶
Изменения в поведении¶
Автокоммит на уровне базы данных включен по умолчанию в Django 1.6. Хотя это не меняет общего духа управления транзакциями в Django, есть несколько несовместимостей в обратную сторону.
Точки сохранения и assertNumQueries
¶
Изменения в управлении транзакциями могут привести к появлению дополнительных операторов для создания, освобождения или отката точек сохранения. Скорее всего, это произойдет с SQLite, поскольку до этого выпуска он не поддерживал точки сохранения.
Если тесты с использованием assertNumQueries()
не работают из-за большего количества запросов, чем ожидалось, проверьте, связаны ли дополнительные запросы с точками сохранения, и скорректируйте ожидаемое количество запросов соответствующим образом.
Опция автокоммита для PostgreSQL¶
В предыдущих версиях автокоммит на уровне базы данных был опцией только для PostgreSQL, и по умолчанию он был отключен. Теперь эта опция игнорируется и может быть удалена.
Новый испытательный стенд¶
Для поддержания большей согласованности с модулем Python unittest
, новый бегунок тестирования (django.test.runner.DiscoverRunner
) не поддерживает автоматически некоторые типы тестов, которые поддерживались предыдущим бегунком:
- Тесты в файлах
models.py
иtests/__init__.py
больше не будут найдены и запущены. Переместите их в файл, имя которого начинается сtest
. - Доктесты больше не будут обнаруживаться автоматически. Чтобы интегрировать доктесты в свой набор тестов, следуйте инструкциям recommendations in the Python documentation.
Django использует модифицированную версию модуля doctest
из стандартной библиотеки Python (в django.test._doctest
) и включает некоторые дополнительные утилиты doctest. Эти утилиты устарели и будут удалены в Django 1.8; наборы doctest должны быть обновлены для работы с модулем doctest стандартной библиотеки (или преобразованы в unittest
-совместимые тесты).
Если вы хотите отложить обновление вашего набора тестов, вы можете установить параметр TEST_RUNNER
в значение django.test.simple.DjangoTestSuiteRunner
, чтобы полностью восстановить старое поведение тестов. DjangoTestSuiteRunner
является устаревшим, но не будет удален из Django до версии 1.8.
Удаление django.contrib.gis.tests.GeoDjangoTestSuiteRunner
GeoDjango custom test runner¶
Это касается разработчиков, работающих над самим приложением GeoDjango, и связано с пунктом выше об изменениях в тестовых бегунках:
Бегунок тестирования django.contrib.gis.tests.GeoDjangoTestSuiteRunner
был удален, и реализованная в нем автономная установка выполнения тестов GeoDjango больше не поддерживается. Для запуска тестов GeoDjango просто используйте новый DiscoverRunner
и укажите приложение django.contrib.gis
.
Пользовательские модели пользователей в тестах¶
Внедрение нового бегуна тестирования также немного изменило способ импорта тестовых моделей. В результате, любой тест, который переопределяет AUTH_USER_MODEL
для проверки поведения с одной из тестовых моделей пользователей Django (django.contrib.auth.tests.custom_user.CustomUser
и django.contrib.auth.tests.custom_user.ExtensionUser
), теперь должен явно импортировать модель User в вашем тестовом модуле:
from django.contrib.auth.tests.custom_user import CustomUser
@override_settings(AUTH_USER_MODEL='auth.CustomUser')
class CustomUserFeatureTests(TestCase):
def test_something(self):
# Test code here ...
Этот импорт заставляет пользовательскую модель пользователя быть зарегистрированной. Без этого импорта тест не сможет подменить пользовательскую модель пользователя, и вы получите сообщение об ошибке:
ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed
Поиск с учетом временных зон day
, month
и week_day
¶
В Django 1.6 появилась поддержка часовых поясов для поиска day
, month
и week_day
, когда USE_TZ
становится True
. Ранее эти поиски выполнялись в UTC независимо от текущего часового пояса.
Для этого требуется time zone definitions in the database. Если вы используете SQLite, вы должны установить pytz. Если вы используете MySQL, вы должны установить pytz и загрузить таблицы часовых поясов с помощью mysql_tzinfo_to_sql.
Добавление QuerySet.datetimes()
¶
Когда был активен time zone support, добавленный в Django 1.4, поиск QuerySet.dates()
давал неожиданные результаты, поскольку агрегация производилась в UTC. Чтобы исправить это, Django 1.6 вводит новый API, QuerySet.datetimes()
. Это требует нескольких изменений в вашем коде.
QuerySet.dates()
возвращает date
объекты¶
QuerySet.dates()
теперь возвращает список date
. Раньше он возвращал список datetime
.
QuerySet.datetimes()
возвращает список datetime
.
QuerySet.dates()
больше не используется на DateTimeField
¶
QuerySet.dates()
вызывает ошибку, если используется на DateTimeField
, когда активна поддержка часовых поясов. Вместо этого используйте QuerySet.datetimes()
.
date_hierarchy
требует определения часового пояса¶
Функция date_hierarchy
в администраторе теперь полагается на QuerySet.datetimes()
, когда она используется на DateTimeField
.
Это требует определения часового пояса в базе данных, когда USE_TZ
является True
. Learn more.
date_list
в общих представлениях требует определения часового пояса¶
По той же причине обращение к date_list
в контексте общего представления, основанного на дате, требует определения часового пояса в базе данных, если представление основано на DateTimeField
, а USE_TZ
является True
. Learn more.
Новые поисковые запросы могут конфликтовать с полями модели¶
Django 1.6 вводит hour
, minute
, и second
поиск по DateTimeField
. Если у вас были поля модели с именами hour
, minute
, или second
, то новый поиск будет конфликтовать с именами ваших полей. Добавьте явный поиск exact
, если это является проблемой.
BooleanField
больше не используется по умолчанию False
¶
Когда у BooleanField
нет явного default
, неявным значением по умолчанию будет None
. В предыдущей версии Django это было False
, но это не совсем точно отражало отсутствие значения.
Код, который полагается на значение по умолчанию False
, может вызвать исключение при сохранении новых экземпляров модели в базе данных, поскольку None
не является приемлемым значением для BooleanField
. Вы должны либо указать default=False
в определении поля, либо убедиться, что поле установлено в True
или False
перед сохранением объекта.
Переводы и комментарии в шаблонах¶
Извлечение переводов после комментариев¶
Извлечение переводимых литералов из шаблонов с помощью команды makemessages
теперь правильно определяет конструкции i18n, если они расположены после комментария типа {#
/ #}
на той же строке. Например:
{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}
Расположение комментариев переводчика¶
Комментарии для переводчиков в шаблонах, указанные с помощью {#
/ #}
, должны находиться в конце строки. Если это не так, комментарии игнорируются, а makemessages
выдаст предупреждение. Например:
{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>
Цитирование в reverse()
¶
При реверсировании URL Django не применял django.utils.http.urlquote
к аргументам перед интерполяцией их в шаблоны URL. Эта ошибка исправлена в Django 1.6. Если вы обошли эту ошибку, применив URL цитирование перед передачей аргументов в reverse()
, это может привести к двойному цитированию. Если это произошло, просто удалите URL-кавычки из вашего кода. Вам также придется заменить специальные символы в URL, используемые в assertRedirects()
, на их кодированные версии.
Хранение IP-адресов в приложении для комментариев¶
Приложение комментариев теперь использует GenericIPAddressField
для хранения IP-адресов комментаторов, чтобы поддерживать комментарии, отправленные с адресов IPv6. До сих пор они хранились в формате IPAddressField
, который предназначен только для поддержки IPv4. При сохранении комментария, отправленного с адреса IPv6, адрес молча усекался в базах данных MySQL и вызывал исключение в Oracle. Вам нужно будет изменить тип столбца в вашей базе данных, чтобы воспользоваться этим изменением.
Для MySQL выполните этот запрос на базе данных вашего проекта:
ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);
Для Oracle выполните этот запрос:
ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));
Если вы не примените это изменение, поведение не изменится: в MySQL адреса IPv6 усекаются молча; в Oracle генерируется исключение. Для баз данных SQLite или PostgreSQL изменение базы данных не требуется.
Процентные литералы в запросах cursor.execute
¶
Когда вы выполняете необработанные SQL-запросы с помощью метода cursor.execute, правило об удвоении процентных литералов (%
) внутри запроса было унифицировано. В прошлом поведение зависело от бэкенда базы данных. Теперь, для всех бэкендов, удваивать литеральные символы процентов нужно только в том случае, если вы также предоставляете параметры замены. Например:
# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])
SQLite
пользователям необходимо проверять и обновлять такие запросы.
Справочный текст полей формы модели для полей ManyToManyField¶
HTML-рендеринг полей формы модели, соответствующих полям модели ManyToManyField
, используемым для получения жестко закодированного предложения:
Удерживайте клавишу «Control» или «Command» на Mac, чтобы выбрать более одного.
(или его перевод в активную локаль) накладывается как легенда справки, отображаемая вдоль них, если ни model
, ни form
help_text
атрибуты не были указаны пользователем (или эта строка была добавлена к любой help_text
, которая была предоставлена).
Поскольку это происходило на уровне модели, не было возможности предотвратить появление текста в случаях, где он не применим, например, в полях форм, реализующих взаимодействие с пользователем без использования клавиатуры и/или мыши.
Начиная с Django 1.6, в качестве временной временной меры по обеспечению обратной совместимости, логика добавления предложения «Hold down…» была перенесена на уровень поля формы модели и изменена таким образом, чтобы добавлять текст только тогда, когда связанный виджет имеет значение SelectMultiple
или выбранные подклассы.
Это изменение может повлиять на вас обратным несовместимым образом, если вы используете пользовательские поля формы модели и/или виджеты для полей модели ManyToManyField
, чьи пользовательские интерфейсы полагаются на автоматическое предоставление упомянутого жестко закодированного предложения. Такие реализации полей форм должны адаптироваться к новому сценарию, обеспечив собственную обработку атрибута help_text
.
Приложения, использующие средства Django model form вместе со встроенной формой Django fields и widgets, не затронуты, но должны быть осведомлены о том, что описано в Изменение текста справки полей формы модели для полей ManyToManyField ниже.
Итерация QuerySet¶
Итерация QuerySet
была изменена для немедленного преобразования всех найденных строк в объекты Model
. В Django 1.5 и более ранних версиях извлеченные строки преобразовывались в объекты Model
кусками по 100.
Существующий код будет работать, но количество строк, преобразованных в объекты, может измениться в некоторых случаях использования. К таким случаям относится частичный цикл по набору запросов или любое использование, которое заканчивается выполнением __bool__
или __contains__
.
Примечательно, что уже в версии 1.5 большинство бэкендов баз данных получали все строки за один раз.
По-прежнему можно лениво преобразовать извлеченные строки в объекты Model
, используя метод iterator()
.
BoundField.label_tag
теперь включает в себя label_suffix
формы.¶
Это соответствует тому, как такие методы, как Form.as_p
и Form.as_ul
отображают метки.
Если вы вручную отображаете label_tag
в своих шаблонах:
{{ form.my_field.label_tag }}: {{ form.my_field }}
вы захотите удалить двоеточие (или любой другой разделитель, который вы используете), чтобы избежать дублирования при обновлении до Django 1.6. Следующий шаблон в Django 1.6 будет отображаться идентично приведенному выше шаблону в Django 1.5, за исключением того, что двоеточие появится внутри элемента <label>
.
{{ form.my_field.label_tag }} {{ form.my_field }}
будет выглядеть примерно так:
<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />
Если вы хотите сохранить текущее поведение отображения label_tag
без label_suffix
, инстанцируйте форму label_suffix=''
. Вы также можете настроить label_suffix
на основе каждого поля, используя новый параметр label_suffix
в label_tag()
.
Представления администратора _changelist_filters
GET параметр¶
Для сохранения и восстановления фильтров представления списка, представления администратора теперь передают GET-параметр _changelist_filters
. Важно, чтобы вы учли это изменение, если у вас есть пользовательские шаблоны администраторов или если ваши тесты полагаются на прежние URL. Если вы хотите вернуться к первоначальному поведению, вы можете установить атрибут preserve_filters
на False
.
django.contrib.auth
сброс пароля использует кодировку base 64 User
PK¶
В прошлых версиях Django использовалась кодировка base 36 для первичного ключа User
в представлениях сброса пароля и URL (django.contrib.auth.views.password_reset_confirm()
). Кодировки base 36 достаточно, если первичный ключ пользователя является целым числом, однако, с введением пользовательских моделей пользователей в Django 1.5, это предположение может перестать быть верным.
django.contrib.auth.views.password_reset_confirm()
был модифицирован, чтобы принимать параметр uidb64
вместо uidb36
. Если вы изменяете это представление, например, в пользовательском шаблоне password_reset_email.html
, обязательно обновите свой код.
Для обеспечения обратной совместимости был добавлен временный шим для django.contrib.auth.views.password_reset_confirm()
, который позволит ссылкам сброса пароля, созданным до Django 1.6, продолжать работать; он будет удален в Django 1.7. Таким образом, пока ваш сайт работает на Django 1.6 более PASSWORD_RESET_TIMEOUT_DAYS
, это изменение не будет иметь никакого эффекта. В противном случае (например, если вы переходите непосредственно с Django 1.5 на Django 1.7), то все ссылки на сброс пароля, созданные до перехода на Django 1.7 или более позднюю версию, не будут работать после обновления.
Кроме того, если у вас есть пользовательские URL-адреса сброса пароля, вам необходимо обновить их, заменив uidb36
на uidb64
и тире, следующее за этим шаблоном, на косую черту. Также добавьте _\-
в список символов, которые могут соответствовать шаблону uidb64
.
Например:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
становится:
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm',
name='password_reset_confirm'),
Возможно, вы также захотите добавить shim для поддержки ссылок сброса старого стиля. Используя приведенный выше пример, вы измените существующий url, заменив django.contrib.auth.views.password_reset_confirm
на django.contrib.auth.views.password_reset_confirm_uidb36
, а также удалите аргумент name
, чтобы он не конфликтовал с новым url:
url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
'django.contrib.auth.views.password_reset_confirm_uidb36'),
Вы можете удалить этот шаблон URL после развертывания вашего приложения с помощью Django 1.6 для PASSWORD_RESET_TIMEOUT_DAYS
.
Сериализация сеанса по умолчанию переключена на JSON¶
Исторически сложилось так, что django.contrib.sessions
использовал pickle
для сериализации данных сессии перед их хранением в бэкенде. Если вы используете signed cookie session backend и SECRET_KEY
известно злоумышленнику (в Django нет врожденной уязвимости, которая могла бы привести к его утечке), злоумышленник может вставить в сессию строку, которая, будучи распакованной, выполнит произвольный код на сервере. Техника для этого проста и легко доступна в интернете. Хотя хранилище сессий cookie подписывает данные, хранящиеся в cookie, чтобы предотвратить подделку, утечка SECRET_KEY
немедленно перерастает в уязвимость удаленного выполнения кода.
От этой атаки можно защититься, если сериализовать данные сессии с помощью JSON, а не pickle
. Для этого в Django 1.5.3 появилась новая настройка SESSION_SERIALIZER
для настройки формата сериализации сессии. Для обратной совместимости, в Django 1.5.3 эта настройка по умолчанию использовала pickle
, но в 1.6 мы изменили значение на JSON. Если вы обновитесь и перейдете с pickle на JSON, сессии, созданные до обновления, будут потеряны. Хотя сериализация JSON не поддерживает все объекты Python, как это делает pickle
, мы настоятельно рекомендуем использовать сериализованные в JSON сессии. Проверяя свой код, чтобы определить, будет ли JSON-сериализация работать в вашем приложении, обратите внимание на следующее:
- JSON требует строковых ключей, поэтому вы, скорее всего, столкнетесь с проблемами, если будете использовать нестроковые ключи в
request.session
. - Установка срока действия сессии путем передачи значений
datetime
вset_expiry()
не будет работать, так как значенияdatetime
не сериализуемы в JSON. Вместо этого вы можете использовать целочисленные значения.
Более подробную информацию см. в документации Сериализация сеанса.
Изменения в объектно-реляционном картографе¶
Django 1.6 содержит множество изменений в ORM. Эти изменения в основном делятся на три категории:
- Исправления ошибок (например, правильные условия присоединения для общих отношений, объединение запросов, продвижение присоединения и обрезка присоединения)
- Подготовка к новым возможностям. Например, ORM теперь внутренне готов к многоколоночным внешним ключам.
- Генеральная уборка.
Эти изменения могут привести к некоторым проблемам совместимости. Например, некоторые запросы теперь будут генерировать разные псевдонимы таблиц. Это может повлиять на QuerySet.extra()
. Кроме того, некоторые запросы теперь будут давать разные результаты. Примером может служить exclude(condition)
, где условие является сложным (обращение к многосвязкам внутри Q objects
). Во многих случаях затронутые запросы не давали правильных результатов в Django 1.5, но теперь дают. К сожалению, есть также случаи, которые дают разные результаты, но ни Django 1.5, ни 1.6 не дают правильных результатов.
Наконец, было внесено много изменений во внутренние API ORM.
Разное¶
django.db.models.query.EmptyQuerySet
больше не может быть инстанцирован - он используется только как класс-маркер для проверки, был ли вызванnone()
:isinstance(qs.none(), EmptyQuerySet)
Если ваш код CSS/JavaScript использовал доступ к виджетам ввода HTML по типу, вам следует пересмотреть его, поскольку виджеты
type='text'
теперь могут быть выведены какtype='email'
,type='url'
илиtype='number'
в зависимости от соответствующего типа поля.Поле формы
error_messages
, содержащее заполнитель, теперь всегда должно использовать именованный заполнитель ("Value '%(value)s' is too big"
вместо"Value '%s' is too big"
). Подробности об именах заполнителей см. в документации к соответствующему полю. Изменения в версии 1.6 особенно затрагиваютDecimalField
иModelMultipleChoiceField
.Некоторые
error_messages
дляIntegerField
,EmailField
,IPAddressField
,GenericIPAddressField
иSlugField
были подавлены, потому что они дублировали сообщения об ошибках, уже предоставленные валидаторами, привязанными к полям.Из-за изменения рабочего процесса валидации формы, метод
TypedChoiceField
coerce
всегда должен возвращать значение, присутствующее в атрибуте поляchoices
. Это ограничение должно быть снова снято в Django 1.7.Были внесены изменения в способ обработки таймаутов в бэкендах кэша. Явная передача значения
timeout=None
больше не приводит к использованию таймаута по умолчанию. Теперь будет установлен неистекающий таймаут. Передача 0 в бэкенд memcache больше не использует таймаут по умолчанию, теперь значение будет устанавливаться и сразу же истекать.Приложение
django.contrib.flatpages
использовалось для установки пользовательских HTTP-заголовков в целях отладки. Эта функциональность не была документирована и делала кэширование неэффективным, поэтому она была удалена вместе с ее общей реализацией, ранее доступной вdjango.core.xheaders
.XViewMiddleware
был перенесен изdjango.middleware.doc
вdjango.contrib.admindocs.middleware
, потому что это деталь реализации admindocs, доказавшая свою непригодность для повторного использования в целом.GenericIPAddressField
теперь будет разрешать значенияblank
только в том случае, если значенияnull
также разрешены. Создание поляGenericIPAddressField
, в которомblank
разрешено, аnull
нет, вызовет ошибку проверки модели, поскольку значенияblank
всегда сохраняются какnull
. Ранее сохранение значенияblank
в поле, которое не допускаетnull
, вызывало исключение базы данных во время выполнения.Если при рендеринге шаблона из метода поднимается исключение
NoReverseMatch
, оно не заглушается. Например,{{ obj.view_href }}
приведет к отказу рендеринга шаблона, еслиview_href()
вызоветNoReverseMatch
. Для тега{% url %}
нет никаких изменений, он вызывает отрисовку шаблона, как всегда, когда поднимаетсяNoReverseMatch
.django.test.Client.logout()
теперь вызываетdjango.contrib.auth.logout()
, который пошлет сигналuser_logged_out()
.Authentication views теперь инвертируются по имени, а не по их расположению в
django.contrib.auth.views
. Если вы используете представления безname
, вам следует обновитьurlpatterns
, чтобы использоватьdjango.conf.urls.url()
с параметромname
. Например:(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')
становится:
url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')
RedirectView
теперь имеет атрибутpattern_name
, который позволяет ему выбирать цель путем инверсии URL.В Django 1.4 и 1.5 пустая строка непреднамеренно не считалась действительным паролем. Это означало, что
set_password()
сохранит пустой пароль как непригодный для использования, как это делаетset_unusable_password()
, и поэтомуcheck_password()
всегда возвращалFalse
для пустых паролей. Это исправлено в данном выпуске: пустые пароли теперь действительны.Админка
changelist_view
ранее принимала GET-параметрpop
для обозначения того, что она должна отображаться во всплывающем окне. Этот параметр был переименован в_popup
, чтобы соответствовать остальным представлениям администратора. Вам следует обновить свои пользовательские шаблоны, если в них используется прежнее имя параметра.validate_email()
теперь принимает адреса электронной почты сlocalhost
в качестве домена.Новая опция
makemessages --keep-pot
предотвращает удаление временного файла .pot, созданного перед созданием файла .po.Недокументированный
django.core.servers.basehttp.WSGIServerException
был удален. Вместо него используйтеsocket.error
, предоставляемый стандартной библиотекой. Это изменение также было выпущено в Django 1.5.5.Подпись метода
django.views.generic.base.RedirectView.get_redirect_url()
изменилась и теперь принимает также позиционные аргументы (*args, **kwargs
). Любая безымянная захваченная группа теперь будет передаваться вget_redirect_url()
, что может привести кTypeError
, если вы не обновите сигнатуру вашего пользовательского метода.
Функции, устаревшие в версии 1.6¶
API для управления транзакциями¶
Управление транзакциями было полностью переработано в Django 1.6, и текущие API устарели:
django.middleware.transaction.TransactionMiddleware
django.db.transaction.autocommit
django.db.transaction.commit_on_success
django.db.transaction.commit_manually
- установка
TRANSACTIONS_MANAGED
django.contrib.comments
¶
Фреймворк комментариев Django был устаревшим и больше не поддерживается. Он будет доступен в Django 1.6 и 1.7, и будет удален в Django 1.8. Большинству пользователей будет лучше использовать собственные решения или хостинговые продукты, такие как Disqus.
Код, ранее известный как django.contrib.comments
, стал still available in an external repository.
Поддержка версий PostgreSQL старше 8.4¶
В декабре 2011 года закончился срок поддержки PostgreSQL 8.2, а в феврале 2013 года - 8.3. Как следствие, Django 1.6 устанавливает 8.4 в качестве минимальной версии PostgreSQL, которую он официально поддерживает.
Настоятельно рекомендуется использовать самую последнюю доступную версию PostgreSQL, чтобы повысить производительность и воспользоваться преимуществами встроенной потоковой репликации, доступной в PostgreSQL 9.x.
Изменения в cycle
и firstof
¶
Система шаблонов обычно экранирует все переменные, чтобы избежать XSS-атак. Однако, по исторической случайности, теги cycle
и firstof
выводят свои аргументы как есть.
Django 1.6 начинает процесс исправления этого несоответствия. Библиотека шаблонов future
предоставляет альтернативные реализации cycle
и firstof
, которые автоэскейпируют свои входы. Если вы используете эти теги, вам рекомендуется включить следующую строку в верхней части ваших шаблонов, чтобы включить новое поведение:
{% load cycle from future %}
или:
{% load firstof from future %}
Теги, реализующие старое поведение, были устаревшими, и в Django 1.8 старое поведение будет заменено новым. Для обеспечения совместимости с будущими версиями Django, существующие шаблоны должны быть изменены для использования версий future
.
При необходимости вы можете временно отключить автоэскейп с помощью mark_safe()
или {% autoescape off %}
.
CACHE_MIDDLEWARE_ANONYMOUS_ONLY
установка¶
CacheMiddleware
и UpdateCacheMiddleware
раньше предоставляли возможность кэшировать запросы, только если они были сделаны не вошедшим в систему пользователем. Этот механизм был в значительной степени неэффективен, поскольку промежуточное ПО правильно учитывает HTTP-заголовок Vary: Cookie
, а этот заголовок устанавливается в самых разных случаях, например:
- доступ к сессии, или
- используя защиту CSRF, которая включена по умолчанию, или
- использование библиотеки на стороне клиента, которая устанавливает cookies, например Google Analytics.
Это заставляет кэш эффективно работать на основе каждой сессии, независимо от настройки CACHE_MIDDLEWARE_ANONYMOUS_ONLY
.
SEND_BROKEN_LINK_EMAILS
установка¶
CommonMiddleware
используется для предоставления базовых отчетов о неработающих ссылках по электронной почте, когда SEND_BROKEN_LINK_EMAILS
установлено значение True
.
Из-за неразрешимых проблем с упорядочиванием между CommonMiddleware
и LocaleMiddleware
, эта функция была выделена в новое промежуточное программное обеспечение: BrokenLinkEmailsMiddleware
.
Если вы полагаетесь на эту функцию, вам следует добавить 'django.middleware.common.BrokenLinkEmailsMiddleware'
к настройкам MIDDLEWARE_CLASSES
и удалить SEND_BROKEN_LINK_EMAILS
из настроек.
_has_changed
метод на виджетах¶
Если вы определили собственные виджеты формы и определили метод _has_changed
на виджете, то теперь вы должны определить этот метод на самом поле формы.
module_name
атрибут _meta модели¶
Model._meta.module_name
был переименован в model_name
. Несмотря на то, что API является частным, он пройдет через обычный путь депривации.
get_(add|change|delete)_permission
методы модели _meta¶
Model._meta.get_(add|change|delete)_permission
методы были устаревшими. Даже если они не были частью публичного API, они также пройдут обычный путь обесценивания. Вы можете заменить их на django.contrib.auth.get_permission_codename('action', Model._meta)
, где 'action'
будет 'add'
, 'change'
, или 'delete'
.
get_query_set
и подобные методы переименованы в get_queryset
¶
Методы, возвращающие QuerySet
, такие как Manager.get_query_set
или ModelAdmin.queryset
, были переименованы в get_queryset
.
Если вы пишете библиотеку, реализующую, например, метод Manager.get_query_set
, и вам нужно поддерживать старые версии Django, вам следует переименовать метод и условно добавить псевдоним со старым именем:
class CustomManager(models.Manager):
def get_queryset(self):
pass # ...
if django.VERSION < (1, 6):
get_query_set = get_queryset
# For Django >= 1.6, models.Manager provides a get_query_set fallback
# that emits a warning when used.
Если вы пишете библиотеку, которая должна вызывать метод get_queryset
и должна поддерживать старые версии Django, вам следует написать:
get_queryset = (some_manager.get_query_set
if hasattr(some_manager, 'get_query_set')
else some_manager.get_queryset)
return get_queryset() # etc
В общем случае, когда пользовательский менеджер реализует свой собственный метод get_queryset
и вызывает этот метод, а также должен работать со старыми версиями Django и библиотеками, которые еще не обновлены, полезно определить метод get_queryset_compat
, как показано ниже, и использовать его внутри вашего менеджера:
class YourCustomManager(models.Manager):
def get_queryset(self):
return YourCustomQuerySet() # for example
if django.VERSION < (1, 6):
get_query_set = get_queryset
def active(self): # for example
return self.get_queryset_compat().filter(active=True)
def get_queryset_compat(self):
get_queryset = (self.get_query_set
if hasattr(self, 'get_query_set')
else self.get_queryset)
return get_queryset()
Это помогает минимизировать необходимые изменения, а также корректно работает в случае подклассов (таких как RelatedManagers
из Django 1.5), которые могут переопределять get_query_set
или get_queryset
.
shortcut
просмотр и URLconf¶
Представление shortcut
было перемещено из django.views.defaults
в django.contrib.contenttypes.views
вскоре после релиза 1.0, но старое расположение не было устаревшим. Эта оплошность была исправлена в Django 1.6, и теперь вам следует использовать новое расположение.
URLconf django.conf.urls.shortcut
также был устаревшим. Если вы включаете его в URLconf, просто замените:
(r'^prefix/', include('django.conf.urls.shortcut')),
с:
(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),
ModelForm
без fields
или exclude
¶
Раньше, если вы хотели, чтобы ModelForm
использовал все поля модели, вы могли просто опустить атрибут Meta.fields
, и все поля были бы использованы.
Это может привести к проблемам безопасности, когда поля добавляются в модель и непреднамеренно автоматически становятся доступными для редактирования конечным пользователям. В некоторых случаях, особенно при использовании булевых полей, эта проблема может быть совершенно незаметной. Это форма Mass assignment vulnerability.
По этой причине такое поведение является устаревшим, и использование опции Meta.exclude
настоятельно не рекомендуется. Вместо этого все поля, предназначенные для включения в форму, должны быть явно перечислены в атрибуте fields
.
Если эта проблема безопасности действительно не применима в вашем случае, есть короткий способ явно указать, что все поля должны быть использованы - используйте специальное значение "__all__"
для атрибута fields:
class MyModelForm(ModelForm):
class Meta:
fields = "__all__"
model = MyModel
Если у вас есть пользовательские ModelForms
, которые нужно использовать только в админке, есть другой вариант. В админке есть свои методы определения полей (fieldsets
и т.д.), поэтому добавление списка полей в ModelForm
является излишним. Вместо этого просто опустите Meta
внутренний класс ModelForm
, или опустите атрибут Meta.model
. Поскольку подкласс ModelAdmin
знает, для какой модели он предназначен, он может добавить необходимые атрибуты, чтобы получить функционирующий ModelForm
. Это поведение работает и для более ранних версий Django.
UpdateView
и CreateView
без явных полей¶
Общие представления CreateView
и UpdateView
, а также все остальное, производное от ModelFormMixin
, уязвимы к проблеме безопасности, описанной в разделе выше, поскольку они могут автоматически создавать ModelForm
, использующее все поля модели.
По этой причине, если вы используете эти представления для редактирования моделей, вы должны также предоставить атрибут fields
(новый в Django 1.6), который представляет собой список полей модели и работает так же, как атрибут ModelForm
Meta.fields
. В качестве альтернативы, вы можете установить атрибут form_class
в ModelForm
, который явно определяет используемые поля. Определение подкласса <<<5 >>> или <<<6 >>> для использования с моделью, но без явного списка полей, является устаревшим.
Изменение текста справки полей формы модели для полей ManyToManyField
¶
Все специальные обработки атрибута help_text
полей модели ManyToManyField
, выполняемые стандартными полями модели или полями формы модели, как описано в Справочный текст полей формы модели для полей ManyToManyField выше, устарели и будут удалены в Django 1.8.
Текст справки этих полей должен быть обработан либо приложениями, либо пользовательскими полями формы, либо виджетами, как это происходит с остальными типами полей модели.