• 3.1
  • 3.2
  • 5.0
  • Версия документации: 6.1

Портирование ваших приложений с Django 0.96 на 1.0.

Django 1.0 в некоторых областях нарушает совместимость с версией 0.96.

Это руководство поможет вам перенести проекты и приложения версии 0.96 на версию 1.0. Первая часть этого документа включает общие изменения, необходимые для работы с версией 1.0. Если после прохождения первой части ваш код по-прежнему не работает, проверьте раздел «Менее распространенные изменения», чтобы найти список менее распространенных проблем совместимости.

См.также

Примечания к выпуску 1.0. В этом документе более подробно объясняются новые функции версии 1.0; руководство по портированию больше направлено на то, чтобы помочь вам быстро обновить код.

Общие изменения

В этом разделе описаны изменения между версиями 0,96 и 1,0, которые необходимо будет внести большинству пользователей.

Используйте Юникод

Замените строковые литералы ('foo') на литералы Юникода (u'foo'). Django теперь повсюду использует строки Unicode. В большинстве случаев необработанные строки будут продолжать работать, но обновление для использования литералов Unicode предотвратит некоторые неясные проблемы.

Подробную информацию см. в Данные Unicode.

Модели

Общие изменения в файле вашей модели:

Переименуйте maxlength в max_length

Переименуйте аргумент maxlength в max_length (это было изменено, чтобы соответствовать полям формы):

Замените __str__ на __unicode__

Замените функцию __str__ вашей модели на метод __unicode__ и убедитесь, что вы используете Unicode`_ (``u'foo') в этом методе.

Удалить prepopulated_from

Удалите аргумент prepopulated_from в полях модели. Он больше не действителен и перемещен в класс ModelAdmin в admin.py. См. раздел «Администратор» ниже для получения более подробной информации об изменениях в администраторе.

Удалить ядро

Удалите аргумент core из полей вашей модели. В этом больше нет необходимости, поскольку эквивалентная функциональность (часть встроенного редактирования) теперь по-другому обрабатывается интерфейсом администратора. Вам не придется беспокоиться о встроенном редактировании, пока вы не перейдете в раздел «Администратор» ниже. А пока удалите все ссылки на core.

Замените class Admin: на admin.py.

Удалите все ваши внутренние объявления класса Admin из ваших моделей. Они ничего не сломают, если вы их оставите, но и ничего не сделают. Чтобы зарегистрировать приложения у администратора, вы переместите эти объявления в файл admin.py; дополнительную информацию см. в разделе «Администратор» ниже.

Пример

Ниже приведен пример файла models.py со всеми изменениями, которые вам необходимо внести:

Старый (0.96) models.py:

class Author(models.Model):
    first_name = models.CharField(maxlength=30)
    last_name = models.CharField(maxlength=30)
    slug = models.CharField(maxlength=60, prepopulate_from=("first_name", "last_name"))

    class Admin:
        list_display = ["first_name", "last_name"]

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)

Новый (1.0) models.py:

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    slug = models.CharField(max_length=60)

    def __unicode__(self):
        return "%s %s" % (self.first_name, self.last_name)

Новый (1.0) admin.py:

from django.contrib import admin
from models import Author


class AuthorAdmin(admin.ModelAdmin):
    list_display = ["first_name", "last_name"]
    prepopulated_fields = {"slug": ("first_name", "last_name")}


admin.site.register(Author, AuthorAdmin)

Администратор

Одно из самых больших изменений в версии 1.0 — новый администратор. Административный интерфейс Django (django.contrib.admin) был полностью переработан; определения администратора теперь полностью отделены от определений модели, инфраструктура была переписана для использования новой библиотеки обработки форм Django и переработана с учетом расширяемости и настройки.

На практике это означает, что вам придется переписать все объявления class Admin. Вы уже видели в models`_ выше, как заменить ваш ``class Admin на вызов admin.site.register() в файле admin.py. Ниже приведены некоторые дополнительные сведения о том, как переписать это объявление Admin в новый синтаксис.

Используйте новый встроенный синтаксис

Все новые параметры edit_inline были перенесены в admin.py. Вот пример:

Старый (0,96):

class Parent(models.Model): ...


class Child(models.Model):
    parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)

Новое (1.0):

class ChildInline(admin.StackedInline):
    model = Child
    extra = 3


class ParentAdmin(admin.ModelAdmin):
    model = Parent
    inlines = [ChildInline]


admin.site.register(Parent, ParentAdmin)

Дополнительную информацию см. в Объект InlineModelAdmin.

Упростите поля или используйте наборы полей.

Старый синтаксис полей был довольно запутанным и был упрощен. Старый синтаксис по-прежнему работает, но вместо него вам придется использовать наборы полей.

Старый (0,96):

class ModelOne(models.Model):
    ...

    class Admin:
        fields = ((None, {"fields": ("foo", "bar")}),)


class ModelTwo(models.Model):
    ...

    class Admin:
        fields = (
            ("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
            ("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
        )

Новое (1.0):

class ModelOneAdmin(admin.ModelAdmin):
    fields = ("foo", "bar")


class ModelTwoAdmin(admin.ModelAdmin):
    fieldsets = (
        ("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
        ("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
    )

См.также

URL-адреса

Обновите корневой файл urls.py.

Если вы используете сайт администратора, вам необходимо обновить корневой файл urls.py.

Старый (0.96) urls.py:

from django.conf.urls.defaults import *

urlpatterns = patterns(
    "",
    (r"^admin/", include("django.contrib.admin.urls")),
    # ... the rest of your URLs here ...
)

Новый (1.0) urls.py:

from django.conf.urls.defaults import *

# The next two lines enable the admin and load each admin.py file:
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns(
    "",
    (r"^admin/(.*)", admin.site.root),
    # ... the rest of your URLs here ...
)

Просмотры

Используйте django.forms вместо newforms.

Замените django.newforms на django.forms - Django 1.0 переименовал модуль newforms (представленный в версии 0.96) в старые добрые forms. Модуль oldforms также был удален.

Если вы уже используете библиотеку newforms и использовали рекомендуемый нами синтаксис операторов импорта, все, что вам нужно сделать, это изменить операторы импорта.

Старый:

from django import newforms as forms

Новый:

from django import forms

Если вы используете старую систему форм (ранее известную как django.forms и django.oldforms), вам придется переписать свои формы. Хорошим местом для начала является документация по формам

Обрабатывайте загруженные файлы с помощью нового API

Замените использование загруженных файлов, то есть записей в request.FILES, как простых словарей, на новый UploadedFile. Старый синтаксис словаря больше не работает.

Таким образом, в представлении типа:

def my_view(request):
    f = request.FILES["file_field_name"]
    ...

…вам необходимо внести следующие изменения:

Старый (0,96)

Новый (1.0)

f['content']

f.read()

f['имя файла']

f.name

f['тип-контента']

f.content_type

Работайте с полями файлов с помощью нового API

Внутренняя реализация django.db.models.FileField изменилась. Видимым результатом этого является то, что изменился способ доступа к специальным атрибутам (URL, имя файла, размер изображения и т. д.) этих полей модели. Вам нужно будет внести следующие изменения, предполагая, что FileField вашей модели называется myfile:

Старый (0,96)

Новый (1.0)

myfile.get_content_filename()

мойфайл.контент.путь

myfile.get_content_url()

myfile.content.url

myfile.get_content_size()

myfile.content.size

myfile.save_content_file()

myfile.content.save()

myfile.get_content_width()

myfile.content.width

myfile.get_content_height()

myfile.content.height

Обратите внимание, что атрибуты width и height имеют смысл только для полей ImageField. Более подробную информацию можно найти в документации model API.

Используйте Paginator вместо ObjectPaginator.

ObjectPaginator в версии 0.96 был удален и заменен улучшенной версией: django.core.paginator.Paginator.

Шаблоны

Научитесь любить автопобег

По умолчанию система шаблонов теперь автоматически экранирует вывод каждой переменной в формате HTML. Чтобы узнать больше, см. Автоматическое экранирование HTML.

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

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

Чтобы отключить автоматическое экранирование для всего шаблона, оберните шаблон (или только определенный раздел шаблона) тегом autoescape:

{% autoescape off %}
   ... unescaped template content here ...
{% endautoescape %}

Менее распространенные изменения

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

Сигналы

  • Добавьте **kwargs ко всем зарегистрированным обработчикам сигналов.

  • Подключайте, отключайте и отправляйте сигналы с помощью методов объекта Signal вместо методов модуля в django.dispatch.dispatcher.

  • Удалите любое использование параметров отправителя «Анонимный» и «Любой»; их больше нет. Вы по-прежнему можете получать сигналы, отправленные любым отправителем, используя sender=None.

  • Превратите любые объявленные вами пользовательские сигналы в экземпляры django.dispatch.Signal вместо анонимных объектов.

Вот краткое описание изменений кода, которые вам необходимо внести:

Старый (0,96)

Новый (1.0)

Обратный вызов по определению (отправитель)

def callback(sender, **kwargs)

подпись = объект()

sig = django.dispatch.Signal()

dispatcher.connect(обратный вызов, сигнал)

sig.connect(обратный вызов)

dispatcher.send(подпись, отправитель)

sig.send(отправитель)

dispatcher.connect(callback, sig, sender=Any)

sig.connect(callback, sender=None)

Комментарии

Если вы использовали приложение django.contrib.comments в Django 0.96, вам необходимо обновиться до нового приложения комментариев, представленного в версии 1.0. Подробности смотрите в руководстве по обновлению.

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

spaceless тег

Тег шаблона spaceless теперь удаляет все пробелы между HTML-тегами вместо сохранения одного пробела.

Местные вкусы

Местный вкус США

django.contrib.localflavor.usa был переименован в django.contrib.localflavor.us. Это изменение было внесено, чтобы соответствовать схеме наименования других местных вкусов. Чтобы перенести код, все, что вам нужно сделать, это изменить импорт.

Сессии

Получение нового сеансового ключа

SessionBase.get_new_session_key() был переименован в _get_new_session_key(). get_new_session_object() больше не существует.

Светильники

Загрузка строки больше не вызывает метод save().

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

Настройки

Лучшие исключения

Старый EnvironmentError разделился на ImportError, когда Django не может найти модуль настроек, и на RuntimeError, когда вы пытаетесь перенастроить настройки после того, как они уже использовались.

LOGIN_URL перемещен

Константа LOGIN_URL перемещена из django.contrib.auth в модуль settings. Вместо использования from django.contrib.auth import LOGIN_URL обратитесь к settings.LOGIN_URL.

APPEND_SLASH поведение было обновлено.

В версии 0.96, если URL-адрес не заканчивался косой чертой или имел точку в последнем компоненте пути, а APPEND_SLASH имел значение True, Django перенаправлял на тот же URL-адрес, но с добавленной косой чертой в конце. Теперь Django проверяет, соответствует ли шаблон без косой черты чему-либо в ваших шаблонах URL. Если да, то перенаправления не происходит, поскольку предполагается, что вы намеренно хотели уловить этот шаблон.

Для большинства людей это не потребует каких-либо изменений. Однако у некоторых людей шаблоны URL-адресов выглядят следующим образом:

r"/some_prefix/(.*)$"

Раньше эти шаблоны перенаправлялись с косой чертой в конце. Если вам всегда нужна косая черта на таких URL-адресах, перепишите шаблон как:

r"/some_prefix/(.*/)$"

Небольшие изменения модели

Другое исключение из get()

Менеджеры теперь возвращают исключение MultipleObjectsReturned вместо AssertionError:

Старый (0,96):

try:
    Model.objects.get(...)
except AssertionError:
    handle_the_error()

Новое (1.0):

try:
    Model.objects.get(...)
except Model.MultipleObjectsReturned:
    handle_the_error()

LazyDate был уволен

Вспомогательный класс LazyDate больше не существует.

Значения полей по умолчанию и аргументы запроса могут быть вызываемыми объектами, поэтому экземпляры LazyDate можно заменить ссылкой на datetime.datetime.now:

Старый (0,96):

class Article(models.Model):
    title = models.CharField(maxlength=100)
    published = models.DateField(default=LazyDate())

Новое (1.0):

import datetime


class Article(models.Model):
    title = models.CharField(max_length=100)
    published = models.DateField(default=datetime.datetime.now)

DecimalField является новым, а FloatField теперь является правильным числом с плавающей запятой.

Старый (0,96):

class MyModel(models.Model):
    field_name = models.FloatField(max_digits=10, decimal_places=3)
    ...

Новое (1.0):

class MyModel(models.Model):
    field_name = models.DecimalField(max_digits=10, decimal_places=3)
    ...

Если вы забудете внести это изменение, вы увидите ошибки о том, что FloatField не принимает атрибут max_digits в __init__, поскольку новый FloatField не принимает аргументов, связанных с точностью.

Если вы используете MySQL или PostgreSQL, никаких дополнительных изменений не требуется. Типы столбцов базы данных для DecimalField такие же, как и для старого FloatField.

Если вы используете SQLite, вам необходимо заставить базу данных просматривать соответствующие столбцы как десятичные типы, а не как числа с плавающей запятой. Для этого вам необходимо перезагрузить данные. Сделайте это после того, как вы внесли изменения в использование DecimalField в своем коде и обновили код Django.

Предупреждение

Сначала создайте резервную копию базы данных!

Для SQLite это означает создание копии единственного файла, в котором хранится база данных (имя этого файла — «DATABASE_NAME» в вашем файле «settings.py»).

Чтобы обновить каждое приложение для использования DecimalField, вы можете сделать следующее, заменив в приведенном ниже коде <app> именем каждого приложения:

$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml

Примечания:

  1. Важно не забыть использовать формат XML на первом этапе этого процесса. Мы используем особенность дампов данных XML, которая делает возможным перенос чисел с плавающей запятой в десятичные числа с помощью SQLite.

  2. На втором этапе вам будет предложено подтвердить, что вы готовы потерять данные для рассматриваемых приложений. Скажи да; мы восстановим эти данные на третьем этапе.

  3. DecimalField не использовался ни в одном из приложений, поставляемых с Django до внесения этого изменения, поэтому вам не нужно беспокоиться о выполнении этой процедуры для любой из стандартных моделей Django.

Если в описанном выше процессе что-то пойдет не так, просто скопируйте резервную копию файла базы данных поверх исходного файла и начните заново.

Интернационализация

django.views.i18n.set_language() теперь требует POST-запроса

Ранее использовался запрос GET. Старое поведение означало, что состояние (язык, используемый для отображения сайта) можно было изменить с помощью запроса GET, что противоречит рекомендациям спецификации HTTP. Код, вызывающий это представление, должен гарантировать, что теперь выполняется запрос POST, а не GET. Это означает, что вы больше не можете использовать ссылку для доступа к представлению, а должны использовать какую-либо отправку формы (например, кнопку).

_() больше нет во встроенных функциях

_() (вызываемый объект, имя которого представляет собой одинарное подчеркивание) больше не добавляется во встроенные функции, то есть он больше не доступен волшебным образом в каждом модуле.

Если раньше вы полагались на постоянное присутствие _(), теперь вам следует явно импортировать ugettext или ugettext_lazy, если это необходимо, и присвоить ему псевдоним _ самостоятельно:

from django.utils.translation import ugettext as _

Объекты HTTP-запроса/ответа

Доступ по словарю к HttpRequest

Объекты HttpRequest больше не поддерживают напрямую доступ в стиле словаря; ранее данные GET и POST были напрямую доступны в объекте HttpRequest (например, вы могли проверить фрагмент данных формы, используя if „some_form_key“ в запросе или прочитав request['some_form_key']. Это больше не поддерживается; если вам нужен доступ к комбинированным данным GET и POST, используйте Вместо этого request.REQUEST.

Однако настоятельно рекомендуется всегда явно искать в соответствующем словаре тип запроса, который вы ожидаете получить («request.GET» или «request.POST»); полагаясь на объединенный словарь request.REQUEST, можно замаскировать происхождение входящих данных.

Доступ к заголовкам HTTPResponse

django.http.HttpResponse.headers был переименован в _headers, и HttpResponse теперь поддерживает прямую проверку содержания. Поэтому используйте if заголовок в ответе: вместо если заголовок в ответе.headers:.

Родовые отношения

Общие отношения были удалены из ядра.

Общие классы отношений — GenericForeignKey и GenericRelation — перемещены в модуль django.contrib.contenttypes.

Тестирование

django.test.Client.login() изменился

Старый (0,96):

from django.test import Client

c = Client()
c.login("/path/to/login", "myuser", "mypassword")

Новое (1.0):

# ... same as above, but then:
c.login(username="myuser", password="mypassword")

Команды управления

Запуск команд управления из вашего кода

django.core.management был значительно переработан.

Для вызовов служб управления в вашем коде теперь необходимо использовать call_command. Например, если у вас есть тестовый код, который вызывает флеш и load_data:

from django.core import management

management.flush(verbosity=0, interactive=False)
management.load_data(["test_data"], verbosity=0)

… вам нужно изменить этот код на следующий:

from django.core import management

management.call_command("flush", verbosity=0, interactive=False)
management.call_command("loaddata", "test_data", verbosity=0)

Подкоманды теперь должны предшествовать опциям

django-admin.py и manage.py теперь требуют, чтобы подкоманды предшествовали опциям. Так:

$ django-admin.py --settings=foo.bar runserver

… больше не работает и его следует изменить на:

$ django-admin.py runserver --settings=foo.bar

Синдикация

Feed.__init__ изменился

Метод __init__() класса Feed платформы распространения теперь принимает объект HttpRequest в качестве второго параметра вместо URL-адреса канала. Это позволяет системе синдикации работать без необходимости использования инфраструктуры сайтов. Это влияет только на код, который является подклассом Feed и переопределяет метод __init__(), а также код, который вызывает Feed.__init__() напрямую.

Структуры данных

SortedDictFromList исчез.

django.newforms.forms.SortedDictFromList был удален. django.utils.datastructures.SortedDict теперь можно создать с помощью последовательности кортежей.

Чтобы обновить код:

  1. Используйте django.utils.datastructures.SortedDict везде, где вы использовали django.newforms.forms.SortedDictFromList.

  2. Поскольку django.utils.datastructures.SortedDict.copy не возвращает глубокую копию, как это сделал SortedDictFromList.copy(), вам придется обновить свой код, если вы полагались на глубокую копию. Сделайте это, используя напрямую copy.deepcopy.

Бэкэнд-функции базы данных

Внутренние функции базы данных были переименованы.

Почти все функции внутреннего уровня базы данных были переименованы и/или перемещены. Ни одна из них не была задокументирована, но вам придется изменить свой код, если вы используете любую из этих функций, все они находятся в django.db:

Старый (0,96)

Новый (1.0)

backend.get_autoinc_sql

connection.ops.autoinc_sql

backend.get_date_extract_sql

connection.ops.date_extract_sql

backend.get_date_trunc_sql

connection.ops.date_trunc_sql

backend.get_datetime_cast_sql

connection.ops.datetime_cast_sql

backend.get_deferrable_sql

connection.ops.deferrable_sql

backend.get_drop_foreignkey_sql

connection.ops.drop_foreignkey_sql

backend.get_fulltext_search_sql

connection.ops.fulltext_search_sql

backend.get_last_insert_id

connection.ops.last_insert_id

backend.get_limit_offset_sql

connection.ops.limit_offset_sql

backend.get_max_name_length

connection.ops.max_name_length

backend.get_pk_default_value

connection.ops.pk_default_value

backend.get_random_function_sql

connection.ops.random_function_sql

backend.get_sql_flush

connection.ops.sql_flush

backend.get_sql_sequence_reset

connection.ops.sequence_reset_sql

backend.get_start_transaction_sql

connection.ops.start_transaction_sql

backend.get_tablespace_sql

connection.ops.tablespace_sql

backend.quote_name

connection.ops.quote_name

backend.get_query_set_class

connection.ops.query_set_class

backend.get_field_cast_sql

connection.ops.field_cast_sql

backend.get_drop_sequence

connection.ops.drop_sequence_sql

бэкенд.OPERATOR_MAPPING

connection.operators

backend.allows_group_by_ordinal

connection.features.allows_group_by_ordinal

backend.allows_unique_and_pk

connection.features.allows_unique_and_pk

backend.autoindexes_primary_keys

connection.features.autoindexes_primary_keys

backend.needs_datetime_string_cast

connection.features.needs_datetime_string_cast

backend.needs_upper_for_iops

connection.features.needs_upper_for_iops

backend.supports_constraints

connection.features.supports_constraints

backend.supports_tablespaces

connection.features.supports_tablespaces

backend.uses_case_insensitivity_names

connection.features.uses_case_insensitivity_names

backend.uses_custom_queryset

connection.features.uses_custom_queryset

Back to Top