Django 3.1 릴리스와 주요 변경 사항
이 글에서는 Django 3.1에 추가된 기능과 바뀐 점을 알아보려 합니다. Django 3.1 release notes를 참고하였습니다.
Django는 3년 마다 LTS를 위해 메이저 버전을 하나씩 올리고, 8개월마다 마이너 버전을 올립니다. 이번에 출시한 3.1은 마이너 업데이트입니다.

파이썬 호환성
Django 3.1은 파이썬 3.6, 3.7, 3.8을 지원합니다. (파이썬 3.5를 지원하는 버전은 Django 2.2.x입니다.)
새 기능
비동기 뷰와 미들웨어
지난 3.0에서 비동기로 작동하는 애플리케이션을 지원하는 기능이 추가되었는데요. 여기에 이어서 비동기 뷰와 미들웨어도 지원합니다. 함수형 뷰라면 다음과 같이 async
키워드만 붙여주면 됩니다.
import time
import asyncio
from django.utils import timezone
async def what_time(request):
before = time.perf_counter()
asyncio.sleep(10)
elapsed = time.perf_counter() - before
result = {
"message": f"Executed in {elapsed} seconds.",
}
return JsonResponse(result)
클래스형 뷰에서는 __call__()
메서드를 정의하라고 하는데, 아직 사용예를 찾지 못해서 추후 코드를 작성해보겠습니다.
모든 데이터베이스에서 JSONField 사용 가능
이전에는 PostgreSQL에서만 사용할 수 있던 JSONField를 모든 데이터베이스에서 사용할 수 있습니다. 따라서 django.contrib.postgres.fields.JSONField
는 향후 사라질 계획입니다.
DEFAULT_HASHING_ALGORITHM
쿠키나 토큰, 사용자 세션 등을 인코딩할 때 사용하던 기본 해시 알고리즘을 지정할 수 있습니다. sha1
과 sha256
을 선택할 수 있으며, 기본 값은 sha256
입니다. 만약 Django 3.1로 이전하고 있는 프로젝트라면, 3.1로 모두 이전하기 전까지는 sha1
로 지정해야 합니다. 이 설정은 Django 4.0에서 SHA-1
알고리즘 지원과 함께 사라질 예정입니다.
그 외 자잘한 변경들
- 관리자 화면(
django.contrib.admin
)-
list_filter
에EmptyFieldListFilter
를 사용하면, 빈 값이나null
로 필터링할 수 있습니다. - 여러 모델을 왔다갔다 할 수 있는 내비게이션이 넓은 해상도에서 나타납니다. (없애고 싶다면
AdminSite.enable_nav_sidebar
값을False
로 지정하면 됩니다.
-
- 인증(
django.contrib.auth
)-
PASSWORD_RESET_TIMEOUT
설정을 변경하면, 비밀번호 초기화 링크의 유효 시간을 지정할 수 있습니다.PASSWORD_RESET_TIMEOUT_DAYS
설정을 사용하고 있었다면 바꾸길 권합니다.PASSWORD_RESET_TIMEOUT_DAYS
설정은 Django 4.0에서 사라질 예정입니다.
-
-
django.contrib.contenttypes
-
remove_stale_contenttypes
명령어에--include-stale-apps
옵션을 사용하면INSTALLED_APPS
에 있었다가 사라진 콘텐트 타입을 지울 수 있습니다.
-
-
django.contrib.gis
- relate 룩업을 MariaDB에서도 지원합니다.
- PostGIS 3와 GDAL 3을 지원합니다.
-
django.contrib.humanize
-
intword
템플릿 필터에서 음수도 지원합니다. 예를 들어-12000000
는-1.2 million
이라고 표시됩니다.
-
-
django.contrib.postgres
- get_FOO_display()가 ArrayField 와 RangeField 를 지원합니다.
-
rangefield.lower_inc와 rangefield.lower_inf, rangefield.upper_inc , rangefield.upper_inf 를 사용하면 RangeField에 대해 경계 값 포함 여부로 룩업 쿼리를 작성할 수 있습니다. (inc는
[
와]
, inf는(
와)
를 의미합니다.) -
RangeField
의contained_by
룩업을SmallAutoField
,AutoField
,BigAutoField
,SmallIntegerField
,DecimalField
에서도 사용할 수 있습니다. - PostgreSQL 11 버전 이상에 추가된
websearch
검색 타입을 SearchQuery에 사용할 수 있습니다. - SearchHeadline 을 사용하면 검색 결과에서 일치하는 부분을 하이라이트할 수 있습니다. (원하는 태그나 기호를 일치하는 부분 앞뒤에 추가하는 방식입니다.)
- search 룩업을 쿼리 표현식에 사용할 수 있습니다.
-
django.contrib.sessions
-
SESSION_COOKIE_SAMESITE
설정에None
을 지정하면, same-site 요청이든 cross-site 요청이든 세션 쿠키를 보냅니다.
-
-
django.contrib.staticfiles
-
STATICFILES_DIRS
설정에 pathlib.Path 객체를 사용할 수 있습니다.
-
-
CSRF
-
CSRF_COOKIE_SAMESITE
설정에None
을 지정하면, same-site 요청이든 cross-site 요청이든 CSRF 쿠키를 보냅니다.
-
- 파일 저장소
-
FileField
와ImageField
의storage
에 호출 가능한 값을 지정할 수 있습니다. (즉, 런타임에 사용할 저장소를 선택할 수 있습니다.)
-
- 관리 명령어
-
check
명령어의--database
옵션에 특정 데이터베이스의 이름을 지정할 수 있습니다. -
migrate
명령어에--check
옵션을 사용하면 적용되지 않은 마이그레이션이 있을 경우 0이 아닌 종료 값을 출력합니다. -
CommandError
에returncode
를 지정할 수 있습니다. -
dbshell
명령어를 사용할 때--
기호 뒤에 커맨드 라인 옵션을 추가할 수 있습니다. (예를 들어./manage.py dbshell -- -c 'select current_user'
)
-
- 모델
- ExtractIsoWeekDay 함수를 사용하면 ISO-8601 표준에 따른 주(week) 번호를 추출할 수 있습니다. 또한 iso_week_day 룩업으로 같은 값을 쿼리할 수 있습니다.
- on_delete에 사용할 수 있는 RESTRICT 옵션이 추가되었습니다.
-
CheckConstraint
의check
값으로 불린 표현식을 지정할 수 있습니다. -
datetimes() 쿼리셋 메서드에
is_dst
를 사용하면, (일광 절약 시간에 적용받는 지역에서) 존재하지 않거나 모호한 시간에 대해 pytz가 예외를 일으키거나 일으키지 않게 할 수 있습니다. - F 표현식에서 bitxor() 메서드를 사용하면 비트 단위의 XOR 연산을 수행할 수 있습니다.
- 요청과 응답
-
ALLOWED_HOSTS 가 빈 값이고
DEBUG=True
로 지정되어 있다면, localhost의 서브 도메인도 허용됩니다. (예를 들어 my.localhost 등) - 새로 추가된 HttpRequest.accepts() 메서드를 사용하면 특정한 MIME 타입인지 여부를 확인할 수 있습니다.
-
ALLOWED_HOSTS 가 빈 값이고
- 보안
-
SECURE_REFERRER_POLICY 설정의 기본 값은
same-origin
으로 바뀌었습니다. 이전처럼 작동하게 하려면None
으로 설정하세요.
-
SECURE_REFERRER_POLICY 설정의 기본 값은
- 템플릿
-
trans
와blocktrans
는translate
와blocktranslate
로 이름이 바뀌었습니다. - include 태그가 템플릿 목록을 지원합니다.
-
- 테스트
- 테스트 데이터베이스 설정에 새로 추가된 MIGRATE 옵션을
False
로 지정하면, 테스트용 데이터베이스를 생성할 때 마이그레이션을 실행하지 않습니다. -
test
명령어에--buffer
옵션을 추가하면, 성공한 테스트에 대해서는 출력을 하지 않습니다. ## 하위 호환이 중단된 기능
- 테스트 데이터베이스 설정에 새로 추가된 MIGRATE 옵션을
- 데이터베이스
- 데이터베이스 연결시
timezone
의 기본 값이UTC
로 설정됩니다.USE_TZ=True
라면TIME_ZONE
값으로 설정됩니다. (이전에는None
이었습니다.)
- 데이터베이스 연결시
- MariaDB 10.1에 대한 지원을 중단합니다.
- 관리자 화면에서 인터넷 익스플로러를 지원하지 않습니다.
-
AbstractUser
의first_name
필드의max_length
값이 150으로 늘어납니다. - 기타
- cache와 make_template_fragment_key()로 생성된 캐시 키가 이전 버전과 달라집니다. 따라서 Django 3.1로 업그레이드한 이후의 첫 요청에 대해서는, 이전에 캐시된 템플릿 조각이라도 캐시 미스가 발생합니다.
-
django.utils.decorators.classproperty()
를 퍼블릭 프로퍼티로 바꾸고, django.utils.functional.classproperty() 로 옮겼습니다. - 반올림하여 0이 되는 음수는 floatformat 템플릿 태그를 사용해도 0을 출력합니다.
- Meta.ordering와 Meta.unique_together를 튜플에서 리스트로 바꾸었습니다.
- dumpdata에서 사용하는 JSON/YAML 시리얼라이저가 기본으로 유니코드를 사용합니다. 이전처럼 작동하게 하려면
ensure_ascii=True
(JSON)나allow_unicode=False
(YAML)을 사용하세요. - 자동 리로딩 서버는 Django 번역 파일의 수정 사항을 추적하지 않습니다.
중단 예정인 기능(화살표 뒤의 기능을 사용하길 권합니다)
-
django.contrib.postgres.fields.JSONField
-> models.JSONField -
django.contrib.postgres.forms.JSONField
-> forms.JSONField -
PASSWORD_RESET_TIMEOUT_DAYS
-> PASSWORD_RESET_TIMEOUT -
django-admin.py
->django-admin
-
HttpRequest.is_ajax()
는 jQuery의 AJAX 호출에 의존적이고 최근에는 자바스크립트의 Fetch API를 선호하는 경향이 있습니다. 상황에 따라 직접 AJAX인지 검사하는 함수를 구현하거나 HttpRequest.accepts() 메서드를 사용하세요. - CookieStorage 와 세션의 인코딩 포맷이 바뀝니다. 이전 형태의 인코딩 포맷은 Django 4.0 이전까지만 지원합니다.
- url 설정시 TemplateView에 직접 kwargs를 적는 방식도 중단될 예정입니다.
-
NullBooleanField
->BooleanField(null=True)
-
django.urls.re_path()의 다른 이름인
django.conf.urls.url()
은 사라질 예정입니다. -
{% ifequal %}
템플릿 태그 ->{% if %}
삭제된 기능
django.utils.timezone.FixedOffset
django.core.paginator.QuerySetPaginator
- 모델의
Meta.ordering
은 더이상 group by 쿼리에 영향을 주지 않습니다. -
django.contrib.postgres.fields.FloatRangeField
와django.contrib.postgres.forms.FloatRangeField
-
FILE_CHARSET
설정 django.contrib.staticfiles.storage.CachedStaticFilesStorage
요약은 여기까지입니다. 개인적으론 중요하지 않아 보여서 적지 않은 내용이 여러분에겐 더 중요할 수도 있으니, Django 3.1 공식 릴리스 노트를 꼼꼼히 살펴보시는 건 어떨까요?