Перенос ваших приложений с Django 0.96 на 1.0 ¶
Django 1.0 в некоторых областях нарушает совместимость с 0.96.
Это руководство поможет вам перенести проекты и приложения 0.96 на 1.0. Первая часть этого документа включает общие изменения, необходимые для работы с 1.0. Если после прохождения первой части ваш код по-прежнему ломается, проверьте раздел « Менее распространенные изменения», чтобы просмотреть список менее распространенных проблем совместимости.
Смотрите также
В версии 1.0 замечания . В этом документе более подробно объясняются новые функции версии 1.0; руководство по портированию больше заботится о том, чтобы помочь вам быстро обновить код.
Общие изменения ¶
В этом разделе описаны изменения между 0.96 и 1.0, которые необходимо внести большинству пользователей.
Используйте Unicode ¶
Измените строковые литералы ( '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
аргумент из полей вашей модели. В этом больше нет необходимости, поскольку эквивалентные функции (часть встроенного редактирования ) теперь по-другому обрабатываются интерфейсом администратора. Вам не нужно беспокоиться о встроенном редактировании, пока вы не попадете в раздел администратора , расположенный ниже. А пока удалите все ссылки на core
.
Заменить на ¶class Admin:
admin.py
Удалите все свои внутренние объявления из ваших моделей. Они ничего не сломают, если вы их оставите, но и ничего не сделают. Чтобы зарегистрировать приложения у администратора, вы переместите эти объявления в файл; см. подробности у администратора ниже.class Admin
admin.py
Смотрите также
Участник djangosnippets написал скрипт, который сканирует ваш models.py и генерирует соответствующий 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 u'%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
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 .
Упростите fields
или используйте fieldsets
¶
Старый fields
синтаксис был довольно запутанным и был упрощен. Старый синтаксис по-прежнему работает, но вам нужно его использовать fieldsets
.
Старая версия (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'}),
)
Смотрите также
- Более подробную информацию об изменениях и причинах их возникновения можно найти на вики-странице NewformsAdminBranch.
- Новый администратор имеет массу новых функций; вы можете прочитать о них в документации администратора .
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
библиотеку и использовали рекомендованный нами
import
синтаксис операторов, все, что вам нужно сделать, это изменить операторы импорта.
Старый:
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['filename'] |
f.name |
f['content-type'] |
f.content_type |
Работа с полями файлов с помощью нового API ¶
Изменилась внутренняя реализация django.db.models.FileField
. Видимым результатом этого является то, что способ доступа к специальным атрибутам (URL, имя файла, размер изображения и т. Д.) Этих полей модели изменился. При условии, что ваша модель FileField
вызывается, вам нужно будет внести следующие изменения
myfile
:
Старый (0.96) | Новое (1.0) |
---|---|
myfile.get_content_filename() |
myfile.content.path |
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
полей. Более подробную информацию можно найти в
документации 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
. - Удалите любое использование опций
Anonymous
иAny
отправителя; они больше не существуют. Вы по-прежнему можете получать сигналы, отправленные любым отправителем, используяsender=None
- Превратите любые объявленные вами пользовательские сигналы в экземпляры,
django.dispatch.Signal
а не в анонимные объекты.
Вот краткое описание изменений кода, которые вам необходимо сделать:
Старый (0.96) | Новое (1.0) |
---|---|
def callback(sender) |
def callback(sender, **kwargs) |
sig = object() |
sig = django.dispatch.Signal() |
dispatcher.connect(callback, sig) |
sig.connect(callback) |
dispatcher.send(sig, sender) |
sig.send(sender) |
dispatcher.connect(callback, sig, sender=Any) |
sig.connect(callback, sender=None) |
Комментарии ¶
Если вы использовали django.contrib.comments
приложение Django 0.96 , вам необходимо перейти на новое приложение для комментариев, представленное в версии 1.0. Подробности см. В руководстве по обновлению.
Теги шаблонов ¶
Местные ароматы ¶
Местный колорит США ¶
django.contrib.localflavor.usa
был переименован в
django.contrib.localflavor.us
. Это изменение было сделано, чтобы соответствовать схеме именования других местных вкусов. Чтобы перенести код, все, что вам нужно сделать, это изменить импорт.
Сессии ¶
Получение нового сеансового ключа ¶
SessionBase.get_new_session_key()
был переименован в
_get_new_session_key()
. get_new_session_object()
больше не существует.
Светильники ¶
Загрузка строки больше не вызывает save()
¶
Раньше при загрузке строки автоматически запускался метод модели save()
. Это уже не так, поэтому любые поля (например, отметки времени), которые были автоматически заполнены a, 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
был истинным, 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
теперь это правильный float ¶
Старая версия (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
Ноты:
- Важно не забыть использовать формат XML на первом этапе этого процесса. Мы используем функцию дампов XML-данных, которая делает возможным перенос чисел с плавающей запятой в десятичные с помощью SQLite.
- На втором этапе вам будет предложено подтвердить, что вы готовы потерять данные для рассматриваемых приложений. Скажи да; мы восстановим эти данные на третьем этапе.
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' in request
request['some_form_key']
GET
POST
request.REQUEST
Однако настоятельно рекомендуется всегда явно искать в соответствующем словаре тип запроса, который вы ожидаете получить ( request.GET
или request.POST
); использование комбинированного
request.REQUEST
словаря позволяет маскировать происхождение входящих данных.
Доступ к HTTPResponse
заголовкам ¶
django.http.HttpResponse.headers
был переименован в _headers
и
HttpResponse
теперь поддерживает проверку содержания напрямую. Так что используйте вместо .if header in response:
if header in response.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
. Например, если у вас есть тестовый код, который вызывает flush и 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
теперь можно создать экземпляр с последовательностью кортежей.
Чтобы обновить свой код:
- Используйте
django.utils.datastructures.SortedDict
везде, где вы использовалиdjango.newforms.forms.SortedDictFromList
. - Поскольку
django.utils.datastructures.SortedDict.copy
не возвращает deepcopy, какSortedDictFromList.copy()
это было, вам нужно будет обновить свой код, если вы полагались на deepcopy. Сделайте это, используя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 |
backend.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_insensitive_names |
connection.features.uses_case_insensitive_names |
backend.uses_custom_queryset |
connection.features.uses_custom_queryset |