Примечания к выпуску Django 1.6¶
Примечание
Посвящается Малкольму Трединнику
17 марта 2013 года проект Django и сообщество свободного программного обеспечения потеряли очень дорогого друга и разработчика.
Малкольм долгое время сотрудничал с Django, образцовым членом сообщества, блестящим умом и другом. Его вклад в Django и многие другие проекты с открытым исходным кодом практически невозможно перечислить. Многие из членов основной команды Django проверяли свои первые патчи; его наставничество обогатило нас. Его внимание, терпение и преданность делу всегда будут для нас источником вдохновения.
Этот выпуск Django предназначен для Малкольма.
– Разработчики Джанго
6 ноября 2013 г.
Добро пожаловать в Джанго 1.6!
Эти примечания к выпуску охватывают новые функции, а также некоторые обратно несовместимые изменения, о которых вам следует знать при обновлении с Django 1.5 или более ранних версий. Мы также удалили некоторые функции, которые подробно описаны в нашем плане прекращения поддержки, и мы начали процесс прекращения поддержки некоторых функций.
Совместимость версий 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.
Что нового в Джанго 1.6¶
Упрощенные шаблоны проектов и приложений по умолчанию.¶
Шаблоны по умолчанию, используемые startproject и startapp, были упрощены и модернизированы. admin теперь включен по умолчанию в новых проектах; платформа sites больше не существует. Предотвращение кликджекинга теперь включено, и по умолчанию используется база данных SQLite.
Если шаблоны по умолчанию вам не подходят, вы можете использовать пользовательские шаблоны проектов и приложений.
Улучшенное управление транзакциями¶
Управление транзакциями Django было переработано. Автофиксация на уровне базы данных теперь включена по умолчанию. Это делает обработку транзакций более явной и должно повысить производительность. Существующие API были объявлены устаревшими, и были введены новые API, как описано в документах по управлению транзакциями.
Постоянные подключения к базе данных¶
Django now supports reusing the same database connection for several requests. This avoids the overhead of re-establishing a connection at the beginning of each request. For backwards compatibility, this feature is disabled by default. See Постоянные соединения с базой данных for details.
Обнаружение тестов в любом тестовом модуле¶
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.
Это изменение обратно несовместимо; см. примечания по обратной несовместимости.
Агрегация с учетом часового пояса¶
Поддержка часовых поясов, представленная в Django 1.4, не работала должным образом с QuerySet.dates(): агрегация всегда выполнялась в формате UTC. Это ограничение было снято в Django 1.6. Используйте QuerySet.datetimes() для выполнения агрегирования с учетом часового пояса в DateTimeField.
Поддержка точек сохранения в SQLite¶
В Django 1.6 добавлена поддержка точек сохранения в SQLite с некоторыми ограничениями <savepoints-in-sqlite>.
Поле модели BinaryField¶
Новое поле модели django.db.models.BinaryField позволяет хранить необработанные двоичные данные в базе данных.
Виджеты форм GeoDjango¶
GeoDjango теперь предоставляет поля форм и виджеты для своих геоспециализированных полей. По умолчанию они основаны на OpenLayers, но их можно настроить для использования любой другой платформы JS.
Добавлена команда управления check для проверки совместимости.¶
Была добавлена команда управления check, позволяющая вам проверить, совместима ли ваша текущая конфигурация (в настоящее время ориентированная на настройки) с текущей версией Django.
Model.save() изменен алгоритм¶
Метод Model.save() теперь пытается напрямую ОБНОВИТЬ базу данных, если экземпляр имеет значение первичного ключа. Ранее SELECT выполнялся, чтобы определить, нужен ли UPDATE или INSERT. Новому алгоритму требуется только один запрос для обновления существующей строки, тогда как старому алгоритму требовалось два. См. Model.save() для более подробной информации.
В некоторых редких случаях база данных не сообщает, что соответствующая строка была найдена при выполнении UPDATE. Примером может служить триггер PostgreSQL ON UPDATE, который возвращает NULL. В таких случаях можно установить флаг django.db.models.Options.select_on_save, чтобы заставить сохранение использовать старый алгоритм.
Минорные изменения¶
Серверные части аутентификации могут вызвать PermissionDenied, чтобы немедленно завершить цепочку аутентификации.
Флаг HttpOnly можно установить в файле cookie CSRF с помощью
CSRF_COOKIE_HTTPONLY.The
assertQuerysetEqual()now checks for undefined order and raisesValueErrorif undefined order is spotted. The order is seen as undefined if the givenQuerySetisn’t ordered and there is more than one ordered value to compare against.Добавлен
earliest()для симметрии сlatest().В дополнение к
год,месяцидень, ORM теперь поддерживаетчас,минутыисекунды.Django теперь оборачивает все исключения PEP 249.
Виджеты по умолчанию для
EmailField,URLField,IntegerField,FloatFieldиDecimalFieldиспользуют новые атрибуты типа, доступные в HTML5. (type='email',type='url',type='number'). Обратите внимание, что из-за неустойчивой поддержки типа ввода «число» с локализованными числами в текущих браузерах, Django использует его только тогда, когда числовые поля не локализованы.Аргумент
numberдля ленивых переводов во множественном числе <lazy-plural-translations>` может быть предоставлен во время перевода, а не во время определения.Для пользовательских команд управления: проверка наличия допустимых настроек в командах, которые запрашивают это, с использованием внутренней опции BaseCommand.can_import_settings теперь выполняется независимо от обработки локали, которая должна быть активна во время выполнения команды. На последнее теперь можно влиять с помощью новой внутренней опции BaseCommand.leave_locale_alone. Дополнительную информацию см. в разделе Команды и локализация.
success_urlDeletionMixinтеперь интерполируется с__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.syndiction) теперь могут передавать дополнительный контекст в шаблоны фидов с помощью нового обратного вызоваFeed.get_context_data().Столбцы списка администраторов имеют в HTML класс
column-<field_name>, поэтому заголовок столбца можно стилизовать с помощью CSS, например чтобы установить ширину столбца.isolation level можно настроить в PostgreSQL.
Тег шаблона
blocktransтеперь учитываетTEMPLATE_STRING_IF_INVALIDдля переменных, отсутствующих в контексте, как и другие конструкции шаблона.SimpleLazyObjects теперь будет предоставлять более полезные представления в ситуациях отладки оболочки.Generic
GeometryFieldтеперь доступен для редактирования с помощью виджета OpenLayers в панели администратора.В документации содержится контрольный список развертывания.
Команда
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 is now the preferred image manipulation library to use with Django. PIL is pending deprecation (support to be removed in Django 1.8). To upgrade, you should first uninstall PIL, then install 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определяет первичные ключи объектов для дампа. Эту опцию можно использовать только с одной моделью.Добавлены методы
QuerySetfirst()иlast(), которые представляют собой удобные методы, возвращающие первый или последний объект, соответствующий фильтрам. Возвращает None, если нет соответствующих объектов.ViewиRedirectViewтеперь поддерживают метод HTTPPATCH.GenericForeignKey теперь принимает необязательный аргумент for_concrete_model, который, если установлено значение False, позволяет полю ссылаться на прокси-модели. По умолчанию установлено значение True, чтобы сохранить старое поведение.
LocaleMiddlewareтеперь сохраняет активный язык в сеансе, если он там отсутствует. Это предотвращает потерю языковых настроек после сброса сеанса, например. выход из системы.SuspiciousOperationбыл разделен на несколько подклассов, и каждый из них будет регистрироваться в соответствующем именованном регистраторе в иерархии журналированияdjango.security. Наряду с этим изменением, механизм handler400 и представление по умолчанию используются всякий раз, когда SuspiciousOperation достигает обработчика WSGI и возвращает HttpResponseBadRequest.Исключение
DoesNotExistтеперь включает сообщение, указывающее имя атрибута, используемого для поиска.Метод
get_or_create()больше не требует хотя бы одного ключевого аргумента.The
SimpleTestCaseclass includes a new assertion helper for testing formset errors:assertFormsetError().Список связанных полей, добавленных в
QuerySetс помощьюselect_lated(), можно очистить с помощьюselect_related(None).Методы
get_extra()иget_max_num()вInlineModelAdminмогут быть переопределены для настройки дополнительного и максимального количества встроенных форм.Наборы форм теперь имеют метод
total_error_count().Поля
ModelFormтеперь могут переопределять сообщения об ошибках, определенные в полях модели, используя аргументerror_messagesконструктораField. Чтобы воспользоваться этой новой функцией с вашими настраиваемыми полями, см. обновленную рекомендацию для создания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 для изменения значения по умолчанию. Пароли будут обновлены, чтобы при необходимости использовать новое количество итераций.
Изменения обратной несовместимости в версии 1.6¶
Предупреждение
В дополнение к изменениям, изложенным в этом разделе, обязательно просмотрите план прекращения поддержки на предмет всех удаленных функций. Если вы не обновили свой код в течение срока прекращения поддержки определенной функции, ее удаление может выглядеть как обратно несовместимое изменение.
Новая модель управления транзакциями¶
Изменения в поведении¶
Автофиксация на уровне базы данных включена по умолчанию в Django 1.6. Хотя это не меняет общего духа управления транзакциями в Django, есть несколько обратных несовместимостей.
Точки сохранения и assertNumQueries¶
Изменения в управлении транзакциями могут привести к появлению дополнительных операторов для создания, освобождения или отката точек сохранения. Это, скорее всего, произойдет с SQLite, поскольку до этого выпуска он не поддерживал точки сохранения.
Если тесты с использованием assertNumQueries() завершаются неудачно из-за большего количества запросов, чем ожидалось, проверьте, связаны ли дополнительные запросы с точками сохранения, и соответствующим образом скорректируйте ожидаемое количество запросов.
Опция автофиксации для PostgreSQL¶
В предыдущих версиях автофиксация на уровне базы данных была доступна только для PostgreSQL и по умолчанию была отключена. Эта опция теперь игнорируется и ее можно удалить.
Новый тестовый бегун¶
Чтобы обеспечить большую согласованность с модулем Unittest Python, новый средство запуска тестов (django.test.runner.DiscoverRunner) не поддерживает автоматически некоторые типы тестов, которые поддерживались предыдущим средством запуска:
Тесты в файлах «models.py» и «tests/__init__.py» больше не будут обнаруживаться и запускаться. Переместите их в файл, имя которого начинается с
test.Доктесты больше не будут обнаруживаться автоматически. Чтобы интегрировать доктесты в свой набор тестов, следуйте рекомендациям в документации Python.
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 для запуска пользовательских тестов.¶
Это для разработчиков, работающих над самим приложением 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 ...
This import forces the custom user model to be registered. Without this import, the test will be unable to swap in the custom user model, and you will get an error reporting:
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 независимо от текущего часового пояса.
Для этого требуются определения часовых поясов в базе данных. Если вы используете SQLite, вам необходимо установить pytz. Если вы используете MySQL, вам необходимо установить pytz и загрузить таблицы часовых поясов с помощью mysql_tzinfo_to_sql.
Добавление QuerySet.datetimes()¶
Когда поддержка часовых поясов </topics/i18n/timezones>`, добавленная в 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. Узнайте больше.
date_list в общих представлениях требует определения часового пояса.¶
По той же причине доступ к date_list в контексте общего представления на основе даты требует определения часового пояса в базе данных, если представление основано на DateTimeField и USE_TZ имеет значение True. Узнайте больше.
Новые запросы могут конфликтовать с полями модели.¶
В Django 1.6 представлены часы, минуты и секунды для поиска в DateTimeField. Если у вас есть поля модели с именами «час», «минута» или «секунда», новые запросы будут конфликтовать с именами ваших полей. Добавьте явный поиск 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, в качестве специального временного обеспечения обратной совместимости, логика добавления предложения «Удерживать…» была перенесена на слой поля формы модели и изменена так, чтобы добавлять текст только тогда, когда связанный виджет является SelectMultiple или выбранными подклассами.
Это изменение может повлиять на вас обратно несовместимым образом, если вы используете пользовательские поля формы модели и/или виджеты для полей модели «ManyToManyField», пользовательский интерфейс которых действительно зависит от автоматического предоставления упомянутого жестко закодированного предложения. Эти реализации полей формы необходимо адаптировать к новому сценарию, предоставив собственную обработку атрибута help_text.
Приложения, использующие возможности Django model form вместе со встроенными fields и widgets Django, не затронуты, но необходимо учитывать то, что описано в Изменение текста справки полей формы модели для полей «ManyToManyField» ниже.
Итерация QuerySet¶
Итерация QuerySet была изменена для немедленного преобразования всех выбранных строк в объекты Model. В Django 1.5 и более ранних версиях выбранные строки конвертировались в объекты «Модель» частями по 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().
Администратор просматривает параметр GET _changelist_filters¶
Чтобы обеспечить сохранение и восстановление фильтров представлений списков, представления администратора теперь передают 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, обязательно обновите свой код.
A temporary shim for django.contrib.auth.views.password_reset_confirm()
that will allow password reset links generated prior to Django 1.6 to continue
to work has been added to provide backwards compatibility; this will be removed
in Django 1.7. Thus, as long as your site has been running Django 1.6 for more
than PASSWORD_RESET_TIMEOUT_DAYS, this change will have no effect.
If not (for example, if you upgrade directly from Django 1.5 to Django 1.7),
then any password reset links generated before you upgrade to Django 1.7 or
later won’t work after the upgrade.
Кроме того, если у вас есть собственные 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'),
Вы также можете добавить прокладку для поддержки ссылок сброса старого стиля. Используя приведенный выше пример, вы должны изменить существующий 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'),
You can remove this URL pattern after your app has been deployed with Django
1.6 for PASSWORD_RESET_TIMEOUT_DAYS.
Сериализация сеанса по умолчанию переключена на JSON¶
Исторически сложилось так, что django.contrib.sessions использовал pickle для сериализации данных сеанса перед сохранением их на сервере. Если вы используете подписанный бэкэнд сеанса cookie и SECRET_KEY известен злоумышленнику (в Django нет встроенной уязвимости, которая могла бы привести к его утечке), злоумышленник может вставить в свой сеанс строку, которая, будучи распакованной, выполняет произвольный код на сервере. Техника выполнения этого проста и легко доступна в Интернете. Хотя хранилище сеансов файлов cookie подписывает данные, хранящиеся в файлах cookie, чтобы предотвратить несанкционированный доступ, утечка SECRET_KEY немедленно перерастает в уязвимость удаленного выполнения кода.
Эту атаку можно смягчить, сериализовав данные сеанса с использованием JSON, а не pickle. Чтобы облегчить это, в Django 1.5.3 появился новый параметр SESSION_SERIALIZER, позволяющий настроить формат сериализации сеанса. В целях обратной совместимости по умолчанию для этого параметра используется pickle в Django 1.5.3, но в версии 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 объектов). Во многих случаях затронутые запросы не давали правильных результатов в 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)s“ слишком велико»`` вместо"Значение '%s' слишком велико"). Подробную информацию об именах заполнителей см. в документации по соответствующему полю. Изменения в версии 1.6 особенно затрагиваютDecimalFieldиModelMultipleChoiceField.Некоторые
error_messagesдляIntegerField,EmailField,IPAddressField,GenericIPAddressFieldиSlugFieldбыли подавлены, поскольку они дублировали сообщения об ошибках, уже предоставленные валидаторами, привязанными к полям.Из-за изменений в рабочем процессе проверки формы метод 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теперь допускает толькопустыезначения, если также разрешенынулевыезначения. Создание GenericIPAddressField, где разрешено значение «blank», а значение «null» нет, приведет к ошибке проверки модели, поскольку значения «blank» всегда сохраняются как «null». Раньше сохранение пустого значения в поле, не допускающем значение null, приводило к исключению базы данных во время выполнения.Если при рендеринге шаблона в методе возникает исключение NoReverseMatch, оно не отключается. Например,
{{ obj.view_href }}приведет к сбою рендеринга шаблона, еслиview_href()вызоветNoReverseMatch. Тег{% url %}не изменяется, он приводит к сбою рендеринга шаблона, как всегда, при вызовеNoReverseMatch.django.test.Client.logout()теперь вызываетdjango.contrib.auth.logout(), который отправит сигналuser_logged_out().Представления аутентификации теперь меняются местами по имени, а не по их местоположению в
django.contrib.auth.views. Если вы используете представления безимени, вам следует обновить ваши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в качестве домена.The new
makemessages --keep-potoption prevents deleting the temporary .pot file generated before creating the .po file.Недокументированное исключение 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.TransactionMiddlewaredjango.db.transaction.autocommitdjango.db.transaction.commit_on_successdjango.db.transaction.commit_manuallyнастройка
TRANSACTIONS_MANAGED
django.contrib.comments¶
Структура комментариев Django устарела и больше не поддерживается. Он будет доступен в Django 1.6 и 1.7 и удален в Django 1.8. Большинству пользователей будет лучше использовать собственное решение или размещенный продукт, такой как Disqus__.
Код, ранее известный как «django.contrib.comments», «все еще доступен во внешнем репозитории»__.
Поддержка версий 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 starts a process to correct this inconsistency. The future
template library provides alternate implementations of cycle and
firstof that autoescape their inputs. If you’re using these tags,
you’re encouraged to include the following line at the top of your templates to
enable the new behavior:
{% load cycle from future %}
или:
{% load firstof from future %}
Теги, реализующие старое поведение, устарели, и в Django 1.8 старое поведение будет заменено новым. Чтобы обеспечить совместимость с будущими версиями Django, существующие шаблоны следует изменить для использования «будущих» версий.
При необходимости вы можете временно отключить автоматическое экранирование с помощью mark_safe() или {% autoescape off %}.
Параметр CACHE_MIDDLEWARE_ANONYMOUS_ONLY¶
CacheMiddleware и UpdateCacheMiddleware используются для обеспечения возможности кэширования запросов, только если они не были сделаны пользователем, вошедшим в систему. Этот механизм был в значительной степени неэффективен, поскольку промежуточное программное обеспечение правильно учитывает HTTP-заголовок Vary: Cookie, и этот заголовок устанавливается в различных случаях, например:
доступ к сеансу или
используя защиту CSRF, которая включена по умолчанию, или
используя клиентскую библиотеку, которая устанавливает файлы cookie, например 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 мета-методы модели¶
Методы 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».
ярлык и URLconf¶
Представление «ярлык» было перемещено из «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 без полей или исключить¶
Раньше, если вы хотели, чтобы ModelForm использовал все поля модели, вы могли просто опустить атрибут Meta.fields, и будут использоваться все поля.
Это может привести к проблемам безопасности, когда поля добавляются в модель и непреднамеренно становятся доступными для редактирования конечным пользователям. В некоторых случаях, особенно с логическими полями, эта проблема может быть совершенно невидимой. Это форма Уязвимости массового назначения.
По этой причине такое поведение считается устаревшим, и использование опции Meta.exclude настоятельно не рекомендуется. Вместо этого все поля, предназначенные для включения в форму, должны быть явно указаны в атрибуте «fields».
Если эта проблема безопасности действительно не применима в вашем случае, есть ярлык, позволяющий явно указать, что следует использовать все поля - используйте специальное значение "__all__" для атрибута полей:
class MyModelForm(ModelForm):
class Meta:
fields = "__all__"
model = MyModel
Если у вас есть собственные ModelForms, которые нужно использовать только в администраторе, есть другой вариант. У администратора есть свои собственные методы определения полей («наборы полей» и т. д.), поэтому добавление списка полей в «ModelForm» является излишним. Вместо этого просто опустите внутренний класс Meta в ModelForm или опустите атрибут Meta.model. Поскольку подкласс ModelAdmin знает, для какой модели он предназначен, он может добавить необходимые атрибуты для получения функционирующей ModelForm. Это поведение также работает для более ранних версий Django.
UpdateView и CreateView без явных полей¶
Общие представления CreateView и UpdateView, а также все остальное, производное от ModelFormMixin, уязвимы для проблем безопасности, описанных в разделе выше, поскольку они могут автоматически создавать ModelForm, который использует все поля для модель.
По этой причине, если вы используете эти представления для редактирования моделей, вы также должны указать атрибут fields (новый в Django 1.6), который представляет собой список полей модели и работает так же, как атрибут ModelForm Meta.fields. В качестве альтернативы вы можете установить атрибут form_class для ModelForm, который явно определяет поля, которые будут использоваться. Определение подкласса UpdateView или CreateView для использования с моделью, но без явного списка полей, устарело.
Изменение текста справки полей формы модели для полей «ManyToManyField»¶
Вся специальная обработка атрибута help_text полей модели ManyToManyField, выполняемая стандартными полями модели или формы модели, как описано в Текст справки полей формы модели для полей ManyToManyField выше, устарела и будет удалена в Django 1.8.
Текст справки в этих полях должен обрабатываться либо приложениями, либо настраиваемыми полями форм, либо виджетами, как и в случае с остальными типами полей модели.