Примечания к выпуску Django 1.2

*17 мая 2010 года.

Добро пожаловать в Django 1.2!

Почти год готовившийся Django 1.2 содержит впечатляющий список new features и множество исправлений ошибок. Эти заметки о выпуске охватывают новые возможности, а также важные изменения, о которых вы должны знать при переходе с Django 1.1 или более старых версий.

Обзор

Django 1.2 представляет несколько больших и важных новых возможностей, включая:

Это только основные моменты; полная информация и полный список возможностей may be found below.

См.также

Django Advent Осветили выход Django 1.2 серией статей и учебников, в которых подробно рассматриваются некоторые из новых возможностей.

Там, где это возможно, эти функции были введены обратно совместимым образом в соответствии с политикой our API stability policy.

Однако несколько функций изменились таким образом, что для некоторых пользователей они окажутся обратно несовместимыми. Большими изменениями являются:

  • Поддержка Python 2.3 была прекращена. Смотрите полное примечание ниже.

  • Новая система защиты от CSRF не имеет обратной совместимости со старой системой. Пользователи старой системы не будут затронуты до тех пор, пока старая система не будет удалена в Django 1.4.

    Однако переход на новую систему защиты от CSRF требует нескольких важных изменений, несовместимых с обратной стороной, которые подробно описаны ниже в CSRF Protection.

  • Авторы пользовательских подклассов Field должны знать, что у ряда методов был изменен прототип, подробно описанный ниже в разделе get_db_prep_*() methods on Field.

  • Внутреннее устройство тегов шаблонов несколько изменилось; авторы пользовательских тегов шаблонов, которые должны хранить состояние (например, пользовательские теги потока управления), должны убедиться, что их код следует новым правилам для stateful template tags.

  • Декораторы user_passes_test(), login_required() и permission_required() из django.contrib.auth применяются только к функциям и больше не работают с методами. Есть простое однострочное исправление detailed below.

Повторимся, это только основные возможности, которые затронут большинство пользователей. Пользователям, переходящим с предыдущих версий Django, настоятельно рекомендуется ознакомиться с полным списком backwards-incompatible changes и списком deprecated features.

Совместимость с Python

Хотя это не новая функция, важно отметить, что Django 1.2 вводит первое изменение в нашей политике совместимости с Python с момента первого публичного дебюта Django. Предыдущие выпуски Django тестировались и поддерживались на версиях Python 2.x, начиная с 2.3; Django 1.2, однако, прекращает официальную поддержку Python 2.3. Таким образом, минимальная версия Python, необходимая для Django, теперь составляет 2.4, а Django тестируется и поддерживается на Python 2.4, 2.5 и 2.6, и будет поддерживаться на еще не вышедшем Python 2.7.

Это изменение должно затронуть лишь небольшое количество пользователей Django, поскольку большинство производителей операционных систем сегодня поставляют Python 2.4 или более новую версию по умолчанию. Однако если вы все еще используете Python 2.3, вам придется придерживаться Django 1.1, пока вы не сможете перейти на новую версию; согласно our support policy, Django 1.1 будет продолжать получать поддержку безопасности до выхода Django 1.3.

Дорожная карта для общей поддержки Python 2.x в Django и возможного перехода на Python 3.x в настоящее время разрабатывается и будет объявлена до выхода Django 1.3.

Что нового в Django 1.2

Поддержка нескольких баз данных

Django 1.2 добавляет возможность использовать more than one database в вашем проекте Django. Запросы к конкретной базе данных могут быть сделаны с помощью метода using() на объектах QuerySet. Отдельные объекты могут быть сохранены в конкретной базе данных путем предоставления аргумента using при вызове save().

Валидация модели

Экземпляры модели теперь поддерживают validating their own data, а поля модели и формы теперь принимают настраиваемые списки validators, определяющие многоразовое, инкапсулированное поведение валидации. Обратите внимание, однако, что валидация по-прежнему должна выполняться явно. Простое обращение к методу save() экземпляра модели не приведет к проверке данных экземпляра.

Улучшенная защита от CSRF

Django теперь имеет значительно улучшенную защиту от Cross-Site Request Forgery (CSRF) attacks. Этот тип атаки возникает, когда вредоносный сайт содержит ссылку, кнопку формы или какой-либо JavaScript, предназначенный для выполнения некоторого действия на вашем сайте, используя учетные данные вошедшего в систему пользователя, который посещает вредоносный сайт в своем браузере. Также рассматривается смежный тип атаки, «login CSRF», когда атакующий сайт обманывает браузер пользователя, заставляя его войти на сайт с чужими учетными данными.

Рамки сообщений

Django теперь включает надежный и настраиваемый messages framework со встроенной поддержкой обмена сообщениями на основе cookie и сессий, как для анонимных, так и для аутентифицированных клиентов. Фреймворк сообщений заменяет устаревший API пользовательских сообщений и позволяет временно хранить сообщения в одном запросе и извлекать их для отображения в последующем запросе (обычно следующем).

Разрешения на уровне объекта

Добавлена основа для указания разрешений на уровне каждого объекта. Хотя в ядре это не реализовано, пользовательский бэкенд аутентификации может предоставить такую реализацию, и она будет использоваться django.contrib.auth.models.User. Дополнительную информацию см. в authentication docs.

Разрешения для анонимных пользователей

Если вы предоставите пользовательский бэкенд auth с параметром supports_anonymous_user, установленным на True, AnonymousUser будет проверять бэкенд на наличие разрешений, как это уже делал User. Это полезно для централизации обработки разрешений - приложения всегда могут делегировать вопрос о том, разрешено ли что-то или нет, бэкенду авторизации/аутентификации. Более подробную информацию см. в authentication docs.

Ослабленные требования к именам пользователей

Встроенное поле User модели username теперь допускает более широкий диапазон символов, включая @, +, . и -.

Бэкенды электронной почты

Теперь вы можете configure the way that Django sends email. Вместо использования SMTP для отправки всей электронной почты, теперь вы можете выбрать настраиваемый почтовый бэкенд для отправки сообщений. Если ваш хостинг-провайдер использует песочницу или какую-то другую не-SMTP технику для отправки почты, теперь вы можете сконструировать почтовый бэкенд, который позволит стандартному mail sending methods Django использовать эти средства.

Это также облегчает отладку отправки почты. Django поставляется с реализацией бэкенда, которая позволяет вам отправлять почту на file, на console, или на memory. Вы даже можете настроить всю электронную почту на thrown away.

«Умный» if тег

Тег if был усовершенствован и стал намного мощнее. Во-первых, мы добавили поддержку операторов сравнения. Больше вам не придется набирать:

{% ifnotequal a b %}
 ...
{% endifnotequal %}

Теперь вы можете это сделать:

{% if a != b %}
 ...
{% endif %}

На самом деле больше нет причин использовать {% ifequal %} или {% ifnotequal %}, если только вы не ностальгирующий тип.

Поддерживаются следующие операторы: ==, !=, <, >, <=, >=, in и not in, которые работают как операторы Python, в дополнение к and, or и not, которые уже поддерживались.

Кроме того, теперь в выражении if можно использовать фильтры. Например:

<div
  {% if user.email|lower == message.recipient|lower %}
    class="highlight"
  {% endif %}
>{{ message }}</div>

Кэширование шаблонов

В предыдущих версиях Django каждый раз, когда вы рендерили шаблон, он перезагружался с диска. В Django 1.2 вы можете использовать cached template loader для загрузки шаблонов один раз, а затем кэшировать результат для каждого последующего рендеринга. Это может привести к значительному повышению производительности, если ваши шаблоны разбиты на множество маленьких подшаблонов (с помощью тегов {% extends %} или {% include %}).

Как побочный эффект, теперь стало намного проще поддерживать языки шаблонов, не относящиеся к Django.

Загрузчики шаблонов на основе классов

В рамках изменений, внесенных для внедрения Template caching и следуя общей тенденции в Django, API загрузчиков шаблонов был изменен для использования механизмов загрузки шаблонов, инкапсулированных в классы Python, в отличие от функций, единственного метода, доступного до Django 1.1.

Все загрузчики шаблонов shipped with Django были перенесены на новый API, но они по-прежнему реализуют API на основе функций, и механизм ядра шаблонов по-прежнему принимает загрузчики на основе функций (встроенные или сторонние), поэтому нет необходимости изменять ваши настройки TEMPLATE_LOADERS в существующих проектах, все будет работать, если вы оставите их нетронутыми до релиза Django 1.3 включительно.

Если вы разработали свои собственные пользовательские загрузчики шаблонов, мы рекомендуем рассмотреть возможность их переноса на реализацию на основе классов, поскольку код обратной совместимости с загрузчиками на основе функций начинает свой процесс обесценивания в Django 1.2 и будет удален в Django 1.4. Описание API, которые должны реализовывать классы загрузчиков, есть в справке по API шаблона, также вы можете изучить исходный код загрузчиков, поставляемых с Django.

Натуральные ключи в светильниках

Теперь приспособления могут ссылаться на удаленные объекты, используя Натуральные ключи. Эта схема поиска является альтернативой обычным ссылкам на объекты в фикстуре, основанным на первичном ключе, улучшая читабельность и решая проблемы, связанные со ссылками на объекты, значение первичного ключа которых не может быть предсказуемым или известным.

Быстрый отказ при проведении испытаний

Как подкоманда test из django-admin.py, так и сценарий runtests.py, используемый для запуска собственного набора тестов Django, теперь поддерживают опцию --failfast. Когда эта опция указана, она заставляет программу запуска тестов завершать работу после обнаружения сбоя вместо того, чтобы продолжать выполнение теста. Кроме того, была улучшена обработка Ctrl-C во время выполнения теста, чтобы вызвать изящный выход из теста, который сообщает подробности о тестах, которые были запущены до прерывания.

BigIntegerField

Модели теперь могут использовать 64-битный тип BigIntegerField.

Улучшенная локализация

В Django internationalization framework добавлено форматирование и обработка форм с учетом локали. Это означает, что, если эта функция включена, даты и числа в шаблонах будут отображаться с использованием формата, заданного для текущей локали. Django также будет использовать локализованные форматы при разборе данных в формах. Более подробную информацию смотрите в Локализация формата.

readonly_fields в ModelAdmin

django.contrib.admin.ModelAdmin.readonly_fields было добавлено для включения нередактируемых полей на страницах добавления/изменения моделей и инлайнов. Поля и вычисляемые значения могут отображаться рядом с редактируемыми полями.

Настраиваемая подсветка синтаксиса

Теперь вы можете использовать переменную окружения DJANGO_COLORS для изменения или отключения цветов, используемых django-admin.py для обеспечения syntax highlighting.

Синдикация фидов как представлений

Syndication feeds теперь можно использовать непосредственно как представления в ваших URLconf. Это означает, что вы можете полностью контролировать структуру URL ваших фидов. Как и любое другое представление, представления фидов передаются объекту request, поэтому вы можете делать все, что обычно делаете с представлением, например, контролировать доступ на основе пользователя или сделать фид именованным URL.

GeoDjango

Наиболее значительной новой функцией GeoDjango в версии 1.2 является поддержка нескольких пространственных баз данных. В результате, следующие spatial database backends теперь включены:

  • django.contrib.gis.db.backends.postgis
  • django.contrib.gis.db.backends.mysql
  • django.contrib.gis.db.backends.oracle
  • django.contrib.gis.db.backends.spatialite

GeoDjango теперь поддерживает богатые возможности, добавленные в релизе PostGIS 1.5. Новые возможности включают поддержку geography type и включение distance queries с неточечными геометриями в географических системах координат.

Была добавлена поддержка полей трехмерной геометрии, которую можно включить, установив ключевое слово dim на 3 в вашем GeometryField. В рамках этой функции были добавлены агрегат Extent3D и метод extent3d() GeoQuerySet.

Методы force_rhr(), reverse_geom() и geohash() GeoQuerySet являются новыми.

Интерфейс GEOS был обновлен для использования потокобезопасных функций библиотеки C, когда они доступны на платформе.

Интерфейс GDAL теперь позволяет пользователю устанавливать spatial_filter для функций, возвращаемых при итерации по Layer.

Наконец, GeoDjango’s documentation теперь включен в Django’s и больше не размещается отдельно на geodjango.org.

Новые символы спецификатора формата тега шаблона now: c и u.

Аргумент now обзавелся двумя новыми символами формата: c для указания, что значение времени даты должно быть отформатировано в формате ISO 8601, и u, позволяющий выводить микросекундную часть значения времени или времени.

Они также доступны в других частях, таких как фильтры шаблонов date и time, библиотека тегов шаблонов humanize и новый фреймворк format localization.

Изменения в 1.2 с обратной совместимостью

Там, где это возможно, новые возможности были введены с обратной совместимостью в соответствии с политикой our API stability policy. Это означает, что практически весь существующий код, который работал с Django 1.1, будет продолжать работать с Django 1.2; такой код, однако, начнет выдавать предупреждения (подробности см. ниже).

Однако несколько функций изменились таким образом, что для некоторых пользователей сразу же возникнет обратная несовместимость. Эти изменения подробно описаны ниже.

Защита от CSRF

Мы внесли большие изменения в способ работы защиты от CSRF, подробно описанные в the CSRF documentation. Вот основные изменения, о которых вы должны знать:

  • CsrfResponseMiddleware и CsrfMiddleware были устаревшими и будут полностью удалены в Django 1.4, в пользу тега шаблона, который должен быть вставлен в формы.

  • Все приложения contrib используют декоратор csrf_protect для защиты представления. Это требует использования тега шаблона csrf_token в шаблоне. Если вы использовали пользовательские шаблоны для представлений contrib, вы ДОЛЖНЫ ПРОЧИТАТЬ ИНСТРУКЦИИ ПО ОБНОВЛЕНИЮ, чтобы исправить эти шаблоны.

    Документация удалена

    Примечания по обновлению были удалены в текущей документации Django. Пожалуйста, обратитесь к документации по Django 1.3 и старше, чтобы найти эти инструкции.

  • CsrfViewMiddleware по умолчанию включается в MIDDLEWARE_CLASSES. Это включает защиту CSRF по умолчанию, поэтому представления, принимающие POST-запросы, должны быть написаны для работы с промежуточным ПО. Инструкции о том, как это сделать, можно найти в документации по CSRF.

  • Весь CSRF переехал из contrib в core (с обратно совместимыми импортами в старых местах, которые устарели и перестанут поддерживаться в Django 1.4).

get_db_prep_*() методы на Field

До версии Django 1.2 пользовательское поле Field имело возможность определения нескольких функций для поддержки преобразования значений Python в значения, совместимые с базой данных. Пользовательское поле могло выглядеть примерно так:

class CustomModelField(models.Field):
    # ...
    def db_type(self):
        # ...

    def get_db_prep_save(self, value):
        # ...

    def get_db_prep_value(self, value):
        # ...

    def get_db_prep_lookup(self, lookup_type, value):
        # ...

В версии 1.2 эти три метода претерпели изменения в прототипе, и были введены два дополнительных метода:

class CustomModelField(models.Field):
    # ...

    def db_type(self, connection):
        # ...

    def get_prep_value(self, value):
        # ...

    def get_prep_lookup(self, lookup_type, value):
        # ...

    def get_db_prep_save(self, value, connection):
        # ...

    def get_db_prep_value(self, value, connection, prepared=False):
        # ...

    def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
        # ...

Эти изменения необходимы для поддержки нескольких баз данных – db_type и get_db_prep_* больше не могут делать никаких предположений относительно базы данных, для которой выполняется подготовка. Аргумент connection теперь предоставляет методам подготовки конкретное соединение, для которого подготавливается значение.

Два новых метода существуют для того, чтобы отличать общие требования к подготовке данных от требований, специфичных для базы данных. Аргумент prepared используется для указания методам подготовки базы данных, была ли выполнена общая подготовка значения. Если неподготовленное (т.е. prepared=False) значение предоставляется вызовам get_db_prep_*(), они должны вызвать соответствующие вызовы get_prep_*() для выполнения общей подготовки данных.

Мы предоставили функции преобразования, которые прозрачно конвертируют функции, придерживающиеся старого прототипа, в функции, совместимые с новым прототипом. Однако эти функции преобразования будут удалены в Django 1.4, поэтому вам следует как можно скорее обновить ваши определения Field для использования нового прототипа.

Если ваши методы get_db_prep_*() не использовали подключение к базе данных, то вы можете перейти на новую версию, переименовав get_db_prep_value() в get_prep_value() и get_db_prep_lookup() в get_prep_lookup(). Если вам требуются преобразования, специфичные для базы данных, то вам необходимо предоставить реализацию get_db_prep_*, которая использует аргумент connection для разрешения значений, специфичных для базы данных.

Теги шаблона Stateful

Теги шаблонов, которые хранят состояние рендеринга в своем подклассе Node, всегда были уязвимы к потоковой безопасности и другим проблемам; однако, начиная с Django 1.2, они также могут вызвать проблемы при использовании с новым cached template loader.

Все встроенные теги шаблонов Django безопасны для использования с кэшированным загрузчиком, но если вы используете пользовательские теги шаблонов, полученные из сторонних пакетов или из вашего собственного кода, вы должны убедиться, что реализация Node для каждого тега является потокобезопасной. Для получения дополнительной информации см. раздел template tag thread safety considerations.

Вам также может понадобиться обновить ваши шаблоны, если вы полагались на то, что реализация тегов шаблонов Django не является потокобезопасной. Наиболее вероятно, что тег cycle может быть затронут таким образом, особенно когда он используется в сочетании с тегом include. Рассмотрим следующий фрагмент шаблона:

{% for object in object_list %}
    {% include "subtemplate.html" %}
{% endfor %}

с subtemplate.html, которая гласит:

{% cycle 'even' 'odd' %}

Используя непотокобезопасный рендерер, существовавший до версии Django 1.2, это выведет:

even odd even odd ...

Используя потокобезопасный рендерер Django 1.2, вы получите:

even even even even ...

Это происходит потому, что каждая визуализация тега include является независимой визуализацией. Когда тег cycle не был потокобезопасным, состояние тега cycle могло просочиться между несколькими рендерингами одного и того же include. Теперь, когда тег cycle стал потокобезопасным, эта утечка больше не происходит.

user_passes_test, login_required и permission_required.

django.contrib.auth.decorators предоставляет декораторы login_required, permission_required и user_passes_test. Ранее было возможно использовать эти декораторы как на функциях (где первый аргумент - „request“), так и на методах (где первый аргумент - „self“, а второй - „request“). К сожалению, в коде, поддерживающем это, были обнаружены недостатки: он работает только в ограниченных обстоятельствах и выдает ошибки, которые очень трудно отладить, когда он не работает.

По этой причине поведение «автоматической адаптации» было удалено, и если вы используете эти декораторы в методах, вам придется вручную применить django.utils.decorators.method_decorator(), чтобы преобразовать декоратор в тот, который работает с методами. Например, вы измените код следующим образом:

class MyClass(object):

    @login_required
    def my_view(self, request):
        pass

к этому:

from django.utils.decorators import method_decorator

class MyClass(object):

    @method_decorator(login_required)
    def my_view(self, request):
        pass

или:

from django.utils.decorators import method_decorator

login_required_m = method_decorator(login_required)

class MyClass(object):

    @login_required_m
    def my_view(self, request):
        pass

Для тех из вас, кто следит за магистралью разработки, это изменение также относится к другим декораторам, введенным с версии 1.1, включая csrf_protect, cache_control и все, что создано с помощью decorator_from_middleware.

if тег меняется

В связи с новыми возможностями тега шаблона if, он больше не принимает „and“, „or“ и „not“ в качестве допустимых имен переменных. Ранее эти строки могли использоваться в качестве имен переменных. Теперь всегда соблюдается статус ключевого слова, и код шаблона, такой как {% if not %} или {% if and %} будет отбрасывать TemplateSyntaxError. Кроме того, in является новым ключевым словом и поэтому не является допустимым именем переменной в этом теге.

LazyObject

LazyObject - это недокументированный, но часто используемый класс, используемый для ленивого обертывания других объектов неизвестного типа.

В Django 1.1 и более ранних версиях он обрабатывал интроспекцию нестандартным образом, в зависимости от обернутых объектов, реализующих публичный метод с именем get_all_members(). Поскольку это могло легко привести к столкновению имен, он был изменен на использование стандартного метода интроспекции Python, включающего __members__ и __dir__().

Если вы использовали LazyObject в своем собственном коде и реализовали метод get_all_members() для обернутых объектов, вам нужно будет сделать пару изменений:

Во-первых, если ваш класс не имеет специальных требований к интроспекции (т.е. вы не реализовали __getattr__() или другие методы, позволяющие обнаружить атрибуты, не обнаруживаемые обычными механизмами), вы можете просто удалить метод get_all_members(). Реализация по умолчанию LazyObject сделает все правильно.

Если у вас более сложные требования к интроспекции, сначала переименуйте метод get_all_members() в __dir__(). Это стандартный метод интроспекции для Python 2.6 и выше. Если вам требуется поддержка версий Python более ранних, чем 2.6, добавьте в класс следующий код:

__members__ = property(lambda self: self.__dir__())

__dict__ на экземплярах модели

Исторически сложилось так, что атрибут __dict__ экземпляра модели содержал только атрибуты, соответствующие полям модели.

Для поддержки нескольких конфигураций баз данных в Django 1.2 добавлен атрибут _state для экземпляров объектов. Этот атрибут появится в __dict__ для экземпляра модели. Если ваш код полагается на итерацию по __dict__ для получения списка полей, вы должны быть готовы обрабатывать или отфильтровывать атрибут _state.

Код статуса завершения работы программы тестирования

Код состояния выхода из программы запуска тестов (tests/runtests.py и python manage.py test) больше не отражает количество проваленных тестов, поскольку провал 256 или более тестов приводил к неправильному коду состояния выхода. Теперь код состояния выхода для бегунка тестирования равен 0 для успеха (нет неудачных тестов) и 1 для любого количества неудачных тестов. При необходимости количество неудачных тестов можно найти в конце выходных данных программы запуска тестов.

ModelForm.is_valid() и ModelForm.errors.

Большая часть работы по валидации для ModelForms была перенесена на уровень модели. В результате, при первом вызове ModelForm.is_valid(), обращении к ModelForm.errors или другом запуске проверки формы, ваша модель будет очищена на месте. Раньше это преобразование происходило при сохранении модели. Если вам нужен немодифицированный экземпляр вашей модели, вы должны передать его копию конструктору ModelForm.

BooleanField на MySQL

В предыдущих версиях Django, BooleanField модели под MySQL возвращало свое значение как 1 или 0, вместо True или False; для большинства людей это не было проблемой, потому что bool является подклассом int в Python. В Django 1.2, однако, BooleanField на MySQL корректно возвращает настоящий bool. Единственный случай, когда это может стать проблемой, это если вы ожидали, что repr из BooleanField выведет 1 или 0.

Изменения в интерпретации max_num в FormSets

В рамках усовершенствований, внесенных в работу с наборами форм, значение и интерпретация параметра max_num по умолчанию для функций django.forms.formsets.formset_factory() и django.forms.models.modelformset_factory() несколько изменились. Это изменение также влияет на то, как аргумент max_num используется для встроенных объектов администратора.

Ранее значением по умолчанию для max_num было 0 (ноль). Наборы форм затем использовали булево значение max_num, чтобы определить, должно ли быть наложено ограничение на количество создаваемых форм. Значение по умолчанию 0 означало, что количество форм в FormSet по умолчанию не ограничено.

Начиная с версии 1.2, значение по умолчанию для max_num было изменено на None, и FormSets будет различать значения None и 0. Значение None указывает, что никаких ограничений на количество форм не должно быть; значение 0 указывает, что должно быть введено максимум 0 форм. Это не обязательно означает, что ни одна форма не будет отображаться - см. подробнее ModelFormSet documentation.

Если вы вручную указывали значение 0 для max_num, вам необходимо обновить определения FormSet и/или администратора.

email_re

Недокументированное регулярное выражение для проверки адресов электронной почты было перемещено из django.form.fields в django.core.validators. Вам нужно будет обновить импорт, если вы его используете.

Функции, устаревшие в версии 1.2

Наконец, в Django 1.2 устарели некоторые функции из предыдущих релизов. Эти функции все еще поддерживаются, но будут постепенно отменяться в течение следующих нескольких циклов выпуска.

Код, использующий любую из перечисленных ниже возможностей, вызовет предупреждение PendingDeprecationWarning в Django 1.2. По умолчанию это предупреждение молчит, но его можно включить с помощью модуля Python warnings, или запустив Python с флагом -Wd или -Wall.

В Django 1.3 эти предупреждения станут DeprecationWarning, что не является молчанием. В Django 1.4 поддержка этих функций будет полностью удалена.

См.также

Более подробную информацию можно найти в документации Django’s release process и в нашей deprecation timeline.`.

Указание баз данных

До версии Django 1.2, Django использовал ряд настроек для контроля доступа к одной базе данных. В Django 1.2 появилась поддержка нескольких баз данных, в результате чего изменился способ определения настроек базы данных.

Любой существующий файл настроек Django будет продолжать работать как ожидается до версии Django 1.4. До этого времени настройки базы данных старого стиля будут автоматически переведены в формат нового стиля.

В старом формате (до версии 1.2) в файле настроек было несколько параметров DATABASE_. Например:

DATABASE_NAME = 'test_db'
DATABASE_ENGINE = 'postgresql_psycopg2'
DATABASE_USER = 'myusername'
DATABASE_PASSWORD = 's3krit'

Теперь эти настройки находятся в словаре с именем DATABASES. Каждый элемент в словаре соответствует одному соединению с базой данных, а имя 'default' описывает соединение с базой данных по умолчанию. Имена настроек также были сокращены. Предыдущий пример настроек теперь выглядит следующим образом:

DATABASES = {
    'default': {
        'NAME': 'test_db',
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'USER': 'myusername',
        'PASSWORD': 's3krit',
    }
}

Это влияет на следующие настройки:

Старая обстановка Новая установка
DATABASE_ENGINE ENGINE
DATABASE_HOST HOST
DATABASE_NAME NAME
DATABASE_OPTIONS OPTIONS
DATABASE_PASSWORD PASSWORD
DATABASE_PORT PORT
DATABASE_USER USER
TEST_DATABASE_CHARSET TEST_CHARSET
TEST_DATABASE_COLLATION TEST_COLLATION
TEST_DATABASE_NAME TEST_NAME

Эти изменения также необходимы, если вы вручную создали соединение с базой данных, используя DatabaseWrapper() из выбранного вами бэкенда базы данных.

В дополнение к изменению структуры, Django 1.2 удаляет специальную обработку для встроенных бэкендов баз данных. Теперь все бэкенды баз данных должны быть указаны полным именем модуля (т.е. django.db.backends.postgresql_psycopg2, а не просто postgresql_psycopg2).

postgresql бэкенд базы данных

Библиотека psycopg1 не обновлялась с октября 2005 года. В результате, бэкенд базы данных postgresql, использующий эту библиотеку, был устаревшим.

Если в настоящее время вы используете бэкенд postgresql, вам следует перейти на использование бэкенда postgresql_psycopg2. Чтобы обновить код, установите библиотеку psycopg2 и измените настройку ENGINE на использование django.db.backends.postgresql_psycopg2.

CSRF response-rewriting middleware

CsrfResponseMiddleware, промежуточное программное обеспечение, которое автоматически вставляло CSRF-токены в формы POST на исходящих страницах, было устаревшим в пользу метода тегов шаблона (см. выше), и будет полностью удалено в Django 1.4. CsrfMiddleware, который включает в себя функциональность CsrfResponseMiddleware и CsrfViewMiddleware, также был устаревшим.

Кроме того, модуль CSRF перешел из contrib в core, и старые импорты устарели, как описано в примечаниях к обновлению.

Документация удалена

Примечания по обновлению были удалены в текущей документации Django. Пожалуйста, обратитесь к документации по Django 1.3 и старше, чтобы найти эти инструкции.

SMTPConnection

Класс SMTPConnection был упразднен в пользу общего API бэкенда электронной почты. Старый код, который явно инстанцировал экземпляр SMTPConnection:

from django.core.mail import SMTPConnection
connection = SMTPConnection()
messages = get_notification_email()
connection.send_messages(messages)

…теперь следует вызвать get_connection() для создания общего почтового соединения:

from django.core.mail import get_connection
connection = get_connection()
messages = get_notification_email()
connection.send_messages(messages)

В зависимости от значения параметра EMAIL_BACKEND, это может не вернуть SMTP-соединение. Если вам явно требуется SMTP-соединение для отправки электронной почты, вы можете явно запросить SMTP-соединение:

from django.core.mail import get_connection
connection = get_connection('django.core.mail.backends.smtp.EmailBackend')
messages = get_notification_email()
connection.send_messages(messages)

Если ваш вызов для построения экземпляра SMTPConnection потребовал дополнительных аргументов, эти аргументы могут быть переданы вызову get_connection():

connection = get_connection('django.core.mail.backends.smtp.EmailBackend', hostname='localhost', port=1234)

API пользовательских сообщений

API для хранения сообщений в модели пользователя Message (через user.message_set.create) теперь устарел и будет удален в Django 1.4 в соответствии со стандартом release process.

Чтобы обновить код, необходимо заменить все экземпляры this:

user.message_set.create('a message')

..:

from django.contrib import messages
messages.add_message(request, messages.INFO, 'a message')

Кроме того, если вы используете этот метод, вам необходимо заменить следующее:

for message in user.get_and_delete_messages():
    ...

…с:

from django.contrib import messages
for message in messages.get_messages(request):
    ...

Для получения дополнительной информации см. полный текст messages documentation. Вы должны немедленно начать обновлять свой код для использования нового API.

Вспомогательные функции формата даты

django.utils.translation.get_date_formats() и django.utils.translation.get_partial_date_formats() были устаревшими в пользу соответствующих вызовов django.utils.formats.get_format(), который является локально-ориентированным, когда USE_L10N установлен в True, и возвращается к настройкам по умолчанию, если установлен в False.

Чтобы получить различные форматы дат, вместо этого напишите так:

from django.utils.translation import get_date_formats
date_format, datetime_format, time_format = get_date_formats()

…использовать:

from django.utils import formats
date_format = formats.get_format('DATE_FORMAT')
datetime_format = formats.get_format('DATETIME_FORMAT')
time_format = formats.get_format('TIME_FORMAT')

Или при прямом форматировании значения даты:

from django.utils import formats
value_formatted = formats.date_format(value, 'DATETIME_FORMAT')

То же самое относится и к глобальным файлам, находящимся в django.forms.fields:

  • DEFAULT_DATE_INPUT_FORMATS
  • DEFAULT_TIME_INPUT_FORMATS
  • DEFAULT_DATETIME_INPUT_FORMATS

Используйте django.utils.formats.get_format() для получения соответствующих форматов.

Бегунки для тестирования на основе функций

Django 1.2 изменяет инструменты прогона тестов, чтобы использовать подход, основанный на классах. Старые средства запуска тестов, основанные на функциях, все еще будут работать, но должны быть обновлены для использования нового class-based runners.

Feed в django.contrib.syndication.feeds

Класс django.contrib.syndication.feeds.Feed был заменен классом django.contrib.syndication.views.Feed. Старый класс feeds.Feed является устаревшим и будет удален в Django 1.4.

Новый класс имеет почти идентичный API, но позволяет использовать экземпляры в качестве представлений. Например, рассмотрим использование старой структуры в следующем URLconf:

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
    'latest': LatestEntries,
    'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)

Используя новый класс Feed, эти фиды могут быть развернуты непосредственно как представления:

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

urlpatterns = patterns('',
    # ...
    (r'^feeds/latest/$', LatestEntries()),
    (r'^feeds/categories/(?P<category_id>\d+)/$', LatestEntriesByCategory()),
    # ...
)

Если вы в настоящее время используете представление feed(), то класс LatestEntries часто не нужно изменять, кроме подкласса нового класса Feed. Исключением является случай, когда Django автоматически определяет имя шаблона для отображения элементов description и title фида (если вы не указали атрибуты title_template и description_template). Вам следует убедиться, что вы всегда указываете атрибуты title_template и description_template или предоставляете методы item_title() и item_description().

Однако LatestEntriesByCategory использует метод get_object() с аргументом bits для указания конкретной категории для показа. В новом классе Feed метод get_object() принимает request и аргументы из URL, поэтому он будет выглядеть следующим образом:

from django.contrib.syndication.views import Feed
from django.shortcuts import get_object_or_404
from myproject.models import Category

class LatestEntriesByCategory(Feed):
    def get_object(self, request, category_id):
        return get_object_or_404(Category, id=category_id)

    # ...

Кроме того, метод get_feed() на классах Feed теперь принимает разные аргументы, что может повлиять на вас, если вы используете классы Feed напрямую. Вместо необязательного аргумента url, теперь он принимает два аргумента: объект, возвращаемый собственным методом get_object(), и текущий объект request.

Чтобы учесть, что классы Feed не инициализируются для каждого запроса, метод __init__() теперь по умолчанию не принимает аргументов. Ранее он принимал slug из URL и объект request.

В соответствии с RSS best practices, RSS-каналы теперь будут включать элемент atom:link. Вам может потребоваться обновить свои тесты, чтобы учесть это.

Для получения дополнительной информации смотрите полный syndication framework documentation.

Идентификаторы технических сообщений

До версии 1.1 Django использовал идентификаторы технических сообщений, чтобы предоставить локализаторам возможность переводить форматы даты и времени. Это были переводимые translation strings, которые можно было распознать, поскольку все они были в верхнем регистре (например, DATETIME_FORMAT, DATE_FORMAT, TIME_FORMAT). Они были упразднены в пользу новой инфраструктуры Локализация формата, которая позволяет локализаторам указывать эту информацию в formats.py файле в соответствующей django/conf/locale/<locale name>/ директории.

GeoDjango

Чтобы обеспечить поддержку нескольких баз данных, внутренние компоненты базы данных GeoDjango были существенно изменены. Самым большим изменением, несовместимым с обратными изменениями, является то, что модуль django.contrib.gis.db.backend был переименован в django.contrib.gis.db.backends, где теперь существует полноценный spatial database backends. В следующих разделах представлена информация о наиболее популярных API, которые были затронуты этими изменениями.

SpatialBackend

До создания отдельных пространственных бэкендов объект django.contrib.gis.db.backend.SpatialBackend предоставлялся в качестве абстракции для ознакомления с возможностями пространственной базы данных. Все атрибуты и процедуры, предоставляемые SpatialBackend, теперь являются частью атрибута ops бэкенда базы данных.

Старый модуль django.contrib.gis.db.backend все еще предоставляется для обратной совместимости для доступа к объекту SpatialBackend, который является просто псевдонимом для модуля ops соединения пространственной базы данных по умолчанию.

Пользователи, которые полагались на недокументированные модули и объекты в django.contrib.gis.db.backend, а не на абстракции, предоставляемые SpatialBackend, должны изменить свой код. Например, следующий импорт, который будет работать в версии 1.1 и ниже:

from django.contrib.gis.db.backend.postgis import PostGISAdaptor

Необходимо изменить:

from django.db import connection
PostGISAdaptor = connection.ops.Adapter

SpatialRefSys и GeometryColumns модели

В предыдущих версиях GeoDjango, django.contrib.gis.db.models имел модели SpatialRefSys и GeometryColumns для запроса таблиц пространственных метаданных OGC spatial_ref_sys и geometry_columns, соответственно.

Хотя эти псевдонимы по-прежнему предоставляются, они предназначены только для соединения с базой данных по умолчанию и существуют только в том случае, если соединение по умолчанию использует поддерживаемый бэкенд пространственной базы данных.

Примечание

Поскольку структура таблиц пространственных метаданных OGC отличается в разных пространственных базах данных, модели SpatialRefSys и GeometryColumns больше не могут быть связаны с именем приложения gis. Таким образом, при использовании метода get_models в следующем примере не будет возвращено ни одной модели:

>>> from django.db.models import get_app, get_models
>>> get_models(get_app('gis'))
[]

Чтобы получить правильные SpatialRefSys и GeometryColumns для вашей пространственной базы данных, используйте методы, предоставляемые пространственным бэкендом:

>>> from django.db import connections
>>> SpatialRefSys = connections['my_spatialite'].ops.spatial_ref_sys()
>>> GeometryColumns = connections['my_postgis'].ops.geometry_columns()

Примечание

При использовании моделей, возвращенных методом spatial_ref_sys() и geometry_columns(), вам все равно придется использовать правильный псевдоним базы данных при запросе на нестандартном соединении. Другими словами, чтобы убедиться, что модели в приведенном выше примере используют правильную базу данных:

sr_qs = SpatialRefSys.objects.using('my_spatialite').filter(...)
gc_qs = GeometryColumns.objects.using('my_postgis').filter(...)

Код языка no

Используемый в настоящее время код языка для норвежского Bokmål no заменяется на более распространенный код языка nb.

Загрузчики шаблонов на основе функций

Django 1.2 изменяет механизм загрузки шаблонов, используя подход, основанный на классах. Старые загрузчики шаблонов на основе функций все еще будут работать, но их следует обновить, чтобы использовать новые загрузчики шаблонов на основе классов.

Вернуться на верх