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는 이제 전체적으로 유니코드 문자열을 사용합니다. 대부분의 경우, 원시 문자열은 계속 작동하지만 유니코드 리터럴을 사용하도록 업데이트하면 모호한 문제를 방지할 수 있습니다.
자세한 내용은 :doc:`/ref/unicode`를 참조하십시오.
모델¶
모델 파일에 대한 일반적인 변경 사항:
``__str__``을 ``__unicode__``로 교체¶
모델의 __str__
함수를 __unicode__
메서드로 바꾸고, 해당 메서드에서 유니코드를 사용`_(``u’foo’`)하고 있는지 확인하세요.
prepopulated_from
제거¶
모델 필드에서 prepopulated_from
인수를 제거하십시오. 이는 더 이상 유효하지 않으며, admin.py``의 ``ModelAdmin
클래스로 이동되었습니다. 관리자 변경에 대한 자세한 내용은 아래의 `관리자`_를 참조하십시오.
코어
제거¶
모델 필드에서 core
인수를 제거하십시오. 이는 동등한 기능(:ref:’인라인 편집 <admin-inlines>’의 일부)이 이제 관리자 인터페이스에서 다르게 처리되기 때문에 더 이상 필요하지 않습니다. 아래의 관리자 섹션에 도달할 때까지 인라인 편집에 대해 걱정할 필요가 없습니다. 지금은 ``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 "%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`_에서 ``admin.py` 파일에서 class Admin``을 ``admin.site.register()
호출로 대체하는 방법을 이미 보았습니다. 다음은 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)
자세한 내용은 :ref:`admin-inlines`을 참조하십시오.
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"}),
)
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 ...
)
뷰¶
newforms
대신 django.forms
사용¶
django.newforms``를 ``django.forms``로 바꾸십시오 -- Django 1.0은 ``newforms
모듈(0.96에 도입됨)을 일반 이전 forms``로 이름을 바꿨습니다. ``oldforms
모듈도 제거되었습니다.
이미 newforms
라이브러리를 사용 중이고, 권장하는 import
문 구문을 사용했다면, import 문을 변경하기만 하면 됩니다.
이전:
from django import newforms as forms
신규:
from django import forms
이전 양식 시스템(이전의 django.forms
및 django.oldforms
)을 사용하는 경우, 양식을 다시 작성해야 합니다. :doc:`양식 문서 </topics/forms/index>`을 통해 시작하는 것이 좋습니다.
새로운 API를 사용하여 업로드된 파일 처리¶
업로드된 파일(즉, request.FILES
항목)의 사용을 새로운 :class:`~django.core.files.uploadedfile.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를 사용하여 파일 필드 작업¶
:class:`django.db.models.FileField`의 내부 구현이 변경되었습니다. 모델 필드의 특수 속성(URL, 파일 이름, 이미지 크기 등)에 액세스하는 방식이 변경되었습니다. 모델의 :class:`~django.db.models.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
필드에만 의미가 있습니다. 자세한 내용은 model API 문서에서 찾을 수 있습니다.
템플릿¶
자동 이스케이핑을 사랑하는 법 배우기¶
기본적으로, 템플릿 시스템은 이제 모든 변수의 출력을 자동으로 HTML 이스케이프 처리합니다. 자세한 내용은 :ref:`automatic-html-escaping`을 참조하십시오.
개별 변수에 대한 자동 이스케이프를 비활성화하려면 safe
필터를 사용하세요:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
전체 템플릿에 대해 자동 이스케이프를 비활성화하려면, 템플릿(또는 템플릿의 특정 섹션)을 autoescape
태그로 래핑합니다:
{% autoescape off %}
... unescaped template content here ...
{% endautoescape %}
일반적이지 않은 변경 사항¶
다음 변경 사항은 더 작고 지역화된 변경 사항입니다. 고급 사용자에게만 영향을 주지만, 목록을 읽고 이러한 사항에 대한 코드를 확인하는 것이 좋습니다.
시그널¶
- 등록된 시그널 처리기에 ``**kwargs``를 추가하십시오.
- ``django.dispatch.dispatcher``의 모듈 메서드 대신
Signal
객체의 메서드를 통해 신호를 연결, 연결 해제 및 전송합니다. 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 0.96의 django.contrib.comments
앱을 사용하고 있었다면, 1.0에 도입된 새로운 코멘트 앱으로 업그레이드해야 합니다. 자세한 내용은 업그레이드 가이드를 참조하세요.
지역 풍미¶
세션¶
픽스처¶
설정¶
더 나은 예외¶
이전 EnvironmentError`는 :exc:`ImportError
(Django가 설정 모듈을 찾는 데 실패할 때)와, RuntimeError
(이미 사용한 후에 설정을 재구성하려고 할 때)로 분할되었습니다.
:setting:`LOGIN_URL`이 이동됨¶
LOGIN_URL
상수가 django.contrib.auth``에서 ``settings
모듈로 이동했습니다. ``from django.contrib.auth import LOGIN_URL``을 사용하는 대신 :setting:`settings.LOGIN_URL <LOGIN_URL>`을 참조하십시오.
APPEND_SLASH
동작이 업데이트되었습니다.¶
0.96에서 URL이 슬래시로 끝나지 않거나, 경로의 마지막 구성 요소에 마침표가 있고 :setting:`APPEND_SLASH`가 True인 경우 Django는 동일한 URL로 리디렉션되지만 끝에 슬래시가 추가됩니다. 이제 Django는 후행 슬래시가 없는 패턴이 URL 패턴의 무언가와 일치하는지 확인합니다. 만약 일치한다면 의도적으로 해당 패턴을 포착하려 했다고 가정하고 리디렉션이 발생하지 않습니다.
대부분의 경우, 아무런 변경이 필요하지 않습니다. 그러나 어떤 사람들은 다음과 같은 URL 패턴을 가지고 있습니다:
r"/some_prefix/(.*)$"
이전에는 이러한 패턴이 후행 슬래시를 갖도록 리디렉션되었습니다. 이러한 URL에 항상 슬래시를 사용하고 싶다면, 패턴을 다음과 같이 다시 작성하세요:
r"/some_prefix/(.*/)$"
더 작은 모델 변경¶
``get()``과 다른 예외¶
매니저는 이제 AssertionError
대신 MultipleObjectsReturned
예외를 리턴합니다.
이전 (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``가 ``__init__``에서 ``max_digits
속성을 사용하지 않는다는 오류가 표시됩니다. 왜냐하면 새로운 ``FloatField``는 정밀도 관련 인수를 사용하지 않기 때문입니다.
MySQL 또는 PostgreSQL을 사용하는 경우, 아무런 추가 변경이 필요하지 않습니다. ``DecimalField``에 대한 데이터베이스 열 유형은 이전 ``FloatField``와 동일합니다.
SQLite를 사용하는 경우, 데이터베이스에서 적절한 열을 부동 소수점이 아닌 십진수 유형으로 다루도록 강제해야 합니다. 이렇게 하려면 데이터를 다시 로드해야 합니다. 코드에서 ``DecimalField``를 사용하도록 변경하고, Django 코드를 업데이트한 후에 이 작업을 수행하십시오.
경고
먼저 데이터베이스를 백업하세요!
SQLite의 경우, 이는 데이터베이스를 저장하는 단일 파일의 복사본을 만드는 것을 의미합니다(해당 파일의 이름은 settings.py
파일의 ``DATABASE_NAME``입니다).
``DecimalField``를 사용하도록 각 애플리케이션을 업그레이드하려면, 아래 코드에서 ``<app>``을 각 앱의 이름으로 대체하여 다음을 수행할 수 있습니다:
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
각주:
- 이 프로세스의 첫 번째 단계에서 XML 형식을 사용하는 것을 기억하는 것이 중요합니다. 우리는 SQLite를 사용하여 부동 소수점을 십진법으로 이식할 수 있는 XML 데이터 덤프의 기능을 이용하고 있습니다.
- 두 번째 단계에서는 해당 응용 프로그램의 데이터를 잃을 준비가 되었는지 확인하라는 메시지가 표시됩니다. ‘네’라고 대답하십시오; 세 번째 단계에서 이 데이터를 복원할 것입니다.
- ``DecimalField``는 이 변경 이전에 Django와 함께 제공되는 앱에서는 일절 사용되지 않으므로, 표준 Django 모델에 대해 이 절차를 수행하는 것에 대해 걱정할 필요가 없습니다.
위의 과정에서 문제가 발생하면, 백업된 데이터베이스 파일을 원본 파일에 복사하고 다시 시작하면 됩니다.
국제화¶
HTTP 요청/응답 객체¶
``HttpRequest``에 대한 사전 액세스¶
HttpRequest
개체는 더 이상 사전 스타일 액세스를 직접 지원하지 않습니다. 이전에는 if 'some_form_key' in request``를 사용하거나 ``request['some_form_key']``를 읽음으로써 ``GET
및 POST
데이터 모두 HttpRequest
객체에서 직접 사용할 수 있었습니다. 이것은 더 이상 지원되지 않습니다. 결합된 GET
및 POST
데이터에 액세스해야 하는 경우, 대신 ``request.REQUEST``를 사용하십시오.
그러나 수신될 것으로 예상되는 요청 유형(request.GET
또는 request.POST
)에 대해 항상 적절한 사전을 명시적으로 찾아볼 것을 강력하게 제안합니다. 결합된 request.REQUEST
사전에 의존하면 들어오는 데이터의 출처를 숨길 수 있습니다.
범용 관계¶
범용 관계가 코어에서 이동됨¶
범용 관계 클래스 – GenericForeignKey
및 GenericRelation
–은 django.contrib.contenttypes
모듈로 이동했습니다.
테스트중¶
관리 명령어¶
코드에서 관리 명령 실행¶
:mod:`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)
신디케이션¶
데이터 구조¶
데이터베이스 백엔드 기능¶
데이터베이스 백엔드 기능의 이름이 변경되었습니다.¶
거의 모든 데이터베이스 백엔드 수준 함수들의 이름이 바뀌거나 재배치되었습니다. 이 중 어느 것도 문서화되지는 않았지만, 이러한 함수들을 사용하는 경우 코드를 변경해야 합니다. 이 함수들은 모두 :mod:`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 |