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 옵션에 CheckConstraintUniqueConstraint를 사용하여, 데이터베이스 제약 조건을 추가할 수 있습니다. 예를 들어 여덟 자 이하로는 비밀번호를 저장하지 않으려고 한다면,

사소한 변경

django.contrib.admin

TabularInline의 컬럼 헤더에 CSS 클래스를 추가할 수 있습니다.

django.contrib.auth

RemoteUserBackend.configure_user()의 첫 번째 인자로 HttpRequest 객체를 전달할 수 있습니다.

django.contrib.postgres

ArrayAggStringAgg를 사용하면서 애그리게이트 객체의 순서를 결정하기 위해 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에서 Watchmanpywatchman 라이브러리를 사용하여, runserver 명령의 파일 변경 감시 성능을 높였습니다.

마이그레이션

  • 마이그레이션 명령이 실행할 내용을 migrate --plan 명령으로 미리 볼 수 있습니다.

모델

  • NullIfReverse 데이터베이스 함수가 추가되었습니다. 이 외에도 수학 관련 데이터베이스 함수가 많이 추가되었습니다.
    • NullIf는 두 인자가 같으면 None을 반환하고, 다르면 첫 인자를 반환합니다.
    • Reverse는 지정된 문자열 필드의 문자를 역순으로 반환합니다. (reverse라는 값이 있었다면, esrever이 반환됩니다.)
    • 수학 계산과 관련하여 절대 값을 반환하는 Abs, 삼각함수 관련 함수인 Cos, Sin, Tan 등과, 올림 값을 반환하는 Ceil, 내림 값을 반환하는 Floor, 라디안 값을 각도로 변환하는 Degrees, 로그 관련 로그, 자연로그, 자연상수, 이 외에도 파이, 나머지를 반환하는 Mod 등 엄청나게 다양한 함수들이 추가되었습니다.
  • 벌크로 추가하려는 데이터 중 데이터베이스 제약에 어긋나는 데이터가 있을 때, 해당 데이터를 무시할 수 있도록 QuerySet.bulk_create() 메서드에 ignore_conflicts 매개변수를 전달할 수 있습니다. (기본 값은 False)
  • ISO-8601 표준에 맞춰 년도를 반환하는 ExtractIsoYear 가 추가되었습니다.
  • 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 전달인자를 사용하면, 중개 모델에 특정 값을 지정할 수 있습니다.

요청과 응답

직렬화

  • 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

하위 호환이 중단된 기능

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 처럼 문자를 자르는 템플릿 필터를 사용하면, 마침표 문자(.) 세 개 대신 말줄임 문자() 하나가 덧붙습니다.
  • 테스트 Clientdjango.utils.http.urlencode()에서 None 값을 만나면 TypeError 예외를 발생시킵니다. (None을 GET이나 POST 데이터로 인코딩할 수 없기 때문입니다.)
  • ping_google 명령에서 기본으로 http 대신 https를 사용합니다. 서비스에서 http를 사용하는 경우를 위해 ping_google –sitemap-uses-http 옵션이 추가되었습니다.
  • AvgStdDev , 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_queriesTransactionTestCase.multi_db, TestCase.multi_db 속성이 사라질 예정입니다. 대신 SimpleTestCase.databases, TransactionTestCase.databases, TestCase.databases를 사용하세요. 아울러, allow_database_queries=Truemulti_db=True 속성을 설정했었다면 databases='__all__'만 설정하셔도 됩니다.

요약은 여기까지입니다. 개인적으론 중요하지 않아 보여서 적지 않은 내용이 여러분에겐 더 중요할 수도 있으니, Django 2.2 공식 릴리스 노트를 꼼꼼히 살펴보시는 건 어떨까요?