Django 2.2 LTS 릴리스와 주요 변경 사항
Django 2.2가 드디어 출시되었습니다. 2.x 버전으로는 첫 LTSLong-term Support Release입니다. 이 글에서는 Django 2.2에 추가된 기능과 바뀐 점을 알아보려 합니다. Django 2.2 공식 릴리스 노트 를 참고하였습니다.
주의! 개인적으로 판단하기에 사소한 사항들은 번역하지 않았고, 릴리스 노트만으로 이해하기가 어려운 기능엔 설명을 조금 보태었습니다.
파이썬 호환성
Django 2.2는 파이썬Python 3.5, 3.6, 3.7에서 작동합니다. 각 버전별 마지막 릴리스를 사용하기를 추천합니다.
새 기능
모델 제약 조건인 CheckConstraint와 UniqueConstraint
모델의 Meta.contraints 옵션에 CheckConstraint와 UniqueConstraint를 사용하여, 데이터베이스 제약 조건을 추가할 수 있습니다. 예를 들어 여덟 자 이하로는 비밀번호를 저장하지 않으려고 한다면,
class CustomUser(models.Model):
password = models.CharField()
class Meta:
constraints = [
models.CheckConstraint(check=models.Q(password__gte=8), name='password_should_longer_than_8'),
]
사소한 변경
django.contrib.admin
TabularInline의 컬럼 헤더에 CSS 클래스를 추가할 수 있습니다.
django.contrib.auth
RemoteUserBackend.configure_user()의 첫 번째 인자로 HttpRequest 객체를 전달할 수 있습니다.
django.contrib.postgres
ArrayAgg와 StringAgg를 사용하면서 애그리게이트 객체의 순서를 결정하기 위해 ordering
인자를 지정할 수 있습니다.
django.contrib.staticfiles
collectstatic –ignore 옵션에 /vender/*.js
같은 패턴을 추가할 수 있습니다.
데이터베이스 백엔드
SQLite에서 QuerySet.iterator()를 실행해도 결과를 일부분씩만 얻을 수 있습니다. (다른 데이터베이스에 대해서는 이미 지원하던 기능인데, 이번에 SQLite에 대해서도 지원하기 시작했습니다.)
제네릭 뷰
dispatch() 전에 뷰 속성을 초기화하는 View.setup 훅이 추가되었습니다.
국제화
아르메니아 언어հայերեն 에 대한 지원과 번역이 추가되었습니다.
관리용 명령어
- –force-color 옵션을 사용하면 실행 결과에 색이 입혀집니다.
- PostgreSQL에서 inspectdb 명령을 사용하면 외래 테이블foreign tables용 모델도 생성해줍니다.
- 오라클과 PostgreSQL에서 inspectdb –include-views 명령을 사용하면, 데이터베이스의 뷰에 대해서도 모델을 생성해줍니다.
- PostgreSQL에서 inspectdb –include-partitions 명령을 사용하면, 파티션 테이블용 모델을 생성해줍니다.
- inspectdb 명령이 오라클과 PostgreSQL에서 DurationField를, SQLite에서 AutoField를 인식합니다.
- 리눅스나 맥OS에서 Watchman과 pywatchman 라이브러리를 사용하여, runserver 명령의 파일 변경 감시 성능을 높였습니다.
마이그레이션
- 마이그레이션 명령이 실행할 내용을
migrate --plan
명령으로 미리 볼 수 있습니다.
$ ./manage.py migrate --plan
Planned operations:
contenttypes.0001_initial
Create model ContentType
Alter unique_together for contenttype (1 constraint(s))
auth.0001_initial
Create model Permission
Create model Group
Create model User
admin.0001_initial
Create model LogEntry
admin.0002_logentry_remove_auto_add
Alter field action_time on logentry
admin.0003_logentry_add_action_flag_choices
Alter field action_flag on logentry
contenttypes.0002_remove_content_type_name
Change Meta options on contenttype
Alter field name on contenttype
Raw Python operation -> IRREVERSIBLE
Remove field name from contenttype
auth.0002_alter_permission_name_max_length
Alter field name on permission
auth.0003_alter_user_email_max_length
Alter field email on user
auth.0004_alter_user_username_opts
Alter field username on user
auth.0005_alter_user_last_login_null
Alter field last_login on user
auth.0006_require_contenttypes_0002
auth.0007_alter_validators_add_error_messages
Alter field username on user
auth.0008_alter_user_username_max_length
Alter field username on user
auth.0009_alter_user_last_name_max_length
Alter field last_name on user
auth.0010_alter_group_name_max_length
Alter field name on group
auth.0011_update_proxy_permissions
Raw Python operation -> Update the content_type of prox…
sessions.0001_initial
Create model Session
- 값을 특정 형태로 시리얼라이즈하고 싶다면 커스텀 시리얼라이저를 사용할 수 있습니다.
모델
-
NullIf와 Reverse 데이터베이스 함수가 추가되었습니다. 이 외에도 수학 관련 데이터베이스 함수가 많이 추가되었습니다.
- NullIf는 두 인자가 같으면 None을 반환하고, 다르면 첫 인자를 반환합니다.
-
Reverse는 지정된 문자열 필드의 문자를 역순으로 반환합니다. (
reverse
라는 값이 있었다면,esrever
이 반환됩니다.) - 수학 계산과 관련하여 절대 값을 반환하는 Abs, 삼각함수 관련 함수인 Cos, Sin, Tan 등과, 올림 값을 반환하는 Ceil, 내림 값을 반환하는 Floor, 라디안 값을 각도로 변환하는 Degrees, 로그 관련 로그, 자연로그, 자연상수, 이 외에도 파이, 나머지를 반환하는 Mod 등 엄청나게 다양한 함수들이 추가되었습니다.
- 벌크로 추가하려는 데이터 중 데이터베이스 제약에 어긋나는 데이터가 있을 때, 해당 데이터를 무시할 수 있도록 QuerySet.bulk_create() 메서드에
ignore_conflicts
매개변수를 전달할 수 있습니다. (기본 값은False
) - ISO-8601 표준에 맞춰 년도를 반환하는 ExtractIsoYear 가 추가되었습니다.
from datetime import datetime
from django.utils import timezone
from django.db.models.functions import ExtractYear
end_2015 = week_1_day_2014_2015 = datetime(2014, 12, 31, 13, 0, tzinfo=timezone.utc)
Movie.objects.create(published_at=end_2015)
Movie.objects.annotate(pub_year=ExtractIsoYear('published_at')).values('pub_year')
# [{'pub_year': 2015}]
-
Model.save()
,QuerySet.update()
,Model.delete()
등에서 쿼리가 단 하나 실행될 때는 성능 향상을 위해 트랜젝션을 시작하지 않습니다. - 쿼리셋에서 애그리게이션 표현식aggregate expressions을 실행할 때 중복된 값을 제거하려면 allow_distinct 매개변수를 전달할 수 있습니다. (기본 값은
False
) - 연관 모델용 메서드인 RelatedManager.add(), create() , remove() , set() , get_or_create(), update_or_create()에서 중개 모델intermediate model을 허용합니다.
through_defaults
전달인자를 사용하면, 중개 모델에 특정 값을 지정할 수 있습니다.
요청과 응답
- 헤더에 접근하기 편하게 HttpRequest.headers가 추가되었습니다.
직렬화
-
serializers.deserialize()
에서 자연 키natural key로 연결된 객체까지 역직렬화deserialize하려면handle_forward_references=True
를 전달하면 됩니다. (이를 가리켜 전방 참조forward reference라고 합니다.)
테스트
- URL이 같은지 확인하는 SimpleTestCase.assertURLEqual() 메서드가 추가되었습니다.
- 응답이 다른 URL로 리디렉션하는지를 확인하는 assertRedirects()도 추가되었습니다.
-
content_type
이'application/json'
일 때 리스트나 터플이 포함된 데이터를 JSON 형태로 자동 직렬화합니다. - 테스트에서 참조되지 않는 데이터베이스는 구성되지 않습니다.skips the setup of databases
URL
- ResolverMatch 클래스에 추가된 route 속성에, URL 패턴의 route가 저장됩니다. 예를 들어
path('users/<id>/', ...)
같은 패턴이 있다면, route에는'users/<id>/'
가 저장됩니다.
Validator
-
MaxValueValidator와 MinValueValidator, MinLengthValidator , MaxLengthValidator의
limit_value
를 확인할 수 있습니다.
하위 호환이 중단된 기능
Django Admin의 actions 수집 방식
Django 관리 도구의 actions에서 부모 ModelAdmin 클래스의 actions를 수집하지 않습니다. 부모 클래스의 actions까지 사용하고 싶다면 파이썬의 기본 상속 방식을 따라, 다음과 같이 해야 합니다.
class SubAdmin(BaseAdmin):
actions = BaseAdmin.actions + ['sub_admin_action']
GDAL 지원
Geo Django에서 GDAL 1.9와 1.10 지원을 중단합니다.
테스트 실행시 초기화용 데이터 마이그레이션
초기화용 데이터 마이그레이션 과정은 기존 데이터베이스가 삭제된 후 테스트의 마지막에 실행됩니다. 이전 버전에서는 테스트 시작 부분에 실행되었는데 이 때문에 test --keepdb
옵션이 제대로 작동하지 않곤 했습니다. (기본 TransactionTestCase를 수정하지 않았다면, 여러분의 테스트 케이스에 아무런 영향을 주지 않을 겁니다.)
sqlparse 라이브러리 의존성 추가
sqlparse
라이브러리 의존성이 추가되었습니다.
cached_property를 alias화하기
일반적인 방식으로는 cached_property
를 alias화할 수 없습니다.
class Sample:
@cached_property
def method_name(self):
return ...
m_name = method_name
대신, 이렇게 할 수 있습니다.
import operator
class Sample:
@cached_property
def method_name(self):
return ...
m_nmae = property(operator.attrgetter('method_name'))
프록시 모델의 권한
이전 버전에서는 프록시 모델에 권한을 설정하더라도, (프록시 모델이 아닌) 구체concrete 모델의 content type이 생성되었습니다. 이제부터는 프록시 모델은 권한을 상속받지 않습니다. 따라서, 프록시 모델에 자체적인 권한을 설정하면 프록시 모델의 content type이 생성됩니다.
class Animal(models.Model):
class Meta:
permissions = (('can_sleep', 'Can sleep'))
class Cat(Animal):
class Meta:
proxy = True
permissions = (('can knead', 'Can knead'))
>>> content_type = ContentType.objects.get_for_model(Cat, for_concrete_model=False)
>>> cat_permissions = Permission.objects.filter(content_type=content_type)
>>> [perm.codename for perm in cat_permissions]
['add_cat', 'change_cat', 'delete_cat', 'view_cat', 'can_knead']
폼의 Media 에셋
폼의 Media 에셋들을 합칠 때 위상 정렬topological sort algorithm 알고리즘을 사용합니다. 이전에 사용하던 쌍 정렬pairwise merging algorithm이 몇몇 경우에 제대로 작동하지 않았기 때문입니다. 이 변화로 인해, 의존성을 명시하지 않은 자바스크립트 파일과 CSS 파일은 제대로 정렬되지 않을 수 있습니다.
예를 들어, django.jQuery
를 의존하는 위젯에서는 폼 미디어 에셋을 정의할 때 반드시 js = ['admin/js/jquery.init.js']
를 명시해야 합니다.
자잘한 변경
- 가독성을 높이기 위해
UUIDField
의 값 중간에 대시가 추가됩니다.550e8400e29b41d4a716446655440000
대신550e8400-e29b-41d4-a716-446655440000
처럼요. - django.utils.text.slugify() 함수는 더이상 HTML로 출력하기에 안전한 값을 반환한다고 판단되지 않습니다no longer marked as HTML safe.
-
urlizetrunc , truncatechars , truncatechars_html , truncatewords , truncatewords_html 처럼 문자를 자르는 템플릿 필터를 사용하면, 마침표 문자(
.
) 세 개 대신 말줄임 문자(…
) 하나가 덧붙습니다. - 테스트 Client 와 django.utils.http.urlencode()에서
None
값을 만나면TypeError
예외를 발생시킵니다. (None
을 GET이나 POST 데이터로 인코딩할 수 없기 때문입니다.) -
ping_google 명령에서 기본으로
http
대신https
를 사용합니다. 서비스에서http
를 사용하는 경우를 위해 ping_google –sitemap-uses-http 옵션이 추가되었습니다. -
Avg 와 StdDev , Variance 애그리게이션 함수에서 입력 값이
Decimal
이면Decimal
형을 반환합니다. (이전에는float
형을 반환)
중단 예정인 기능
Meta.ordering이 GROUP BY에 영향을 끼치지 않음
모델의 Meta.ordering 속성은 GROUP BY 쿼리에 영향을 끼치지 않습니다. 이런 식의 쿼리를 작성하면 order_by()
를 추가하라는 안내문이 나타나며, Django 3.1부터는 이런 식의 쿼리가 무시될 예정입니다.
자잘한 변경
-
django.core.paginator.Paginator
의 축약 표현이자 문서에는 없었던QuerySetPaginator
가 사라질 예정입니다. - postgres에서 사용하던 모델과 폼의
FloatRangeField
가 사라질 예정이므로, 새 이름인DecimalRangeField
을 사용하세요. -
FILE_CHARSET
설정 값이 사라질 예정입니다. Django 3.1부터 디스크에서 읽는 파일은 반드시 UTF-8로 인코딩되어 있어야 합니다. - 다루기 어려운 문제가 있는
django.contrib.staticfiles.storage.CachedStaticFilesStorage
가 사라질 예정입니다. ManifestStaticFilesStorage나 서드파티의 클라우드 스토리지를 사용하세요. -
SimpleTestCase.allow_database_queries와 TransactionTestCase.multi_db, TestCase.multi_db 속성이 사라질 예정입니다. 대신 SimpleTestCase.databases, TransactionTestCase.databases, TestCase.databases를 사용하세요. 아울러,
allow_database_queries=True
와multi_db=True
속성을 설정했었다면databases='__all__'
만 설정하셔도 됩니다.
요약은 여기까지입니다. 개인적으론 중요하지 않아 보여서 적지 않은 내용이 여러분에겐 더 중요할 수도 있으니, Django 2.2 공식 릴리스 노트를 꼼꼼히 살펴보시는 건 어떨까요?