Django 5.0 リリースノート¶
2023年12月4日
Django 5.0 へようこそ!
このリリースノートでは、 バージョン5.0の新機能 と、Django 4.2以前からアップグレードする際に注意すべき、いくつかの 後方互換性のない変更 について説明します。また今回、 一部機能の廃止プロセスを開始 しました。
既存のプロジェクトをアップデートするときは、 Django の新しいバージョンへの更新 ガイドに従ってください。
Python バージョン間の互換性¶
Django 5.0 は Python 3.10、3.11、および3.12をサポートしています。各バージョン系列の最終リリースのみが公式にサポートされるので、そのいずれかを使用することを 強く推奨 します。
Django 4.2.x シリーズは Python 3.8 と 3.9 をサポートする最後のバージョンになります。
古いバージョンの Django をサポートするサードパーティのライブラリ¶
Django 5.0 リリース後は、サードパーティアプリの開発者は 4.2 より前のバージョンの Django のサポートを終了することを推奨します。このとき、python -Wd
を使ったパッケージテストを実行して、廃止予定 (deprecation) の警告を出力できます。廃止予定の警告が出ないように修正すれば、アプリケーションは Django 5.0 と互換性のある状態になっているはずです。
Django 5.0の新機能¶
管理サイトのファセットフィルター¶
適用されたフィルターのファセット数が、UIを介して切り替えられた場合に、管理者の変更リストで表示されるようになりました。この動作は、新しい ModelAdmin.show_facets
属性を介して変更することができます。詳細については、 ファセット (Facet) を参照してください。
フォームフィールドレンダリング用の簡略化されたテンプレート¶
Django 5.0 から、フィールドグループとフィールドグループテンプレートの概念が導入されます。これにより、Djangoフォームフィールドの関連要素(ラベル、ウィジェット、ヘルプテキスト、エラーなど)のレンダリングが簡略化されます。
たとえば、以下のテンプレートがあるとします。
<form>
...
<div>
{{ form.name.label_tag }}
{% if form.name.help_text %}
<div class="helptext" id="{{ form.name.auto_id }}_helptext">
{{ form.name.help_text|safe }}
</div>
{% endif %}
{{ form.name.errors }}
{{ form.name }}
<div class="row">
<div class="col">
{{ form.email.label_tag }}
{% if form.email.help_text %}
<div class="helptext" id="{{ form.email.auto_id }}_helptext">
{{ form.email.help_text|safe }}
</div>
{% endif %}
{{ form.email.errors }}
{{ form.email }}
</div>
<div class="col">
{{ form.password.label_tag }}
{% if form.password.help_text %}
<div class="helptext" id="{{ form.password.auto_id }}_helptext">
{{ form.password.help_text|safe }}
</div>
{% endif %}
{{ form.password.errors }}
{{ form.password }}
</div>
</div>
</div>
...
</form>
これを、以下のように簡略化できるようになりました:
<form>
...
<div>
{{ form.name.as_field_group }}
<div class="row">
<div class="col">{{ form.email.as_field_group }}</div>
<div class="col">{{ form.password.as_field_group }}</div>
</div>
</div>
...
</form>
as_field_group()
は、デフォルトでは "django/forms/field.html"
テンプレートでフィールドをレンダリングします。プロジェクト、フィールド、またはリクエストごとにカスタマイズできます。詳しくは 再利用可能なフィールドグループテンプレート を参照してください。
データベースで計算されたデフォルト値¶
新しい Field.db_default
パラメータは、データベースで計算されるデフォルト値を設定します。次に例を示します。
from django.db import models
from django.db.models.functions import Now, Pi
class MyModel(models.Model):
age = models.IntegerField(db_default=18)
created = models.DateTimeField(db_default=Now())
circumference = models.FloatField(db_default=2 * Pi())
データベースで生成されるモデルフィールド¶
新しい GeneratedField
により、データベースで生成されるカラムを作成することが可能になりました。このフィールドは、他のフィールドから常に計算されるフィールドを作成するので、すべてのサポートされているデータベースバックエンドで使用することができます。次に例を示します。
from django.db import models
from django.db.models import F
class Square(models.Model):
side = models.IntegerField()
area = models.GeneratedField(
expression=F("side") * F("side"),
output_field=models.BigIntegerField(),
db_persist=True,
)
フィールドの選択肢を宣言する際のオプションが増加¶
Field.choices
(モデルフィールド用) と ChoiceField.choices
(フォームフィールド用) により、値を宣言する際の柔軟性が向上しました。以前のバージョンの Django では、 choices
は 2 タプルのリストか、 列挙型 のサブクラスである必要がありましたが、後者の場合、 .choices
属性にアクセスして、期待される形式で値を提供する必要がありました:
from django.db import models
Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")
SPORT_CHOICES = [
("Martial Arts", [("judo", "Judo"), ("karate", "Karate")]),
("Racket", [("badminton", "Badminton"), ("tennis", "Tennis")]),
("unknown", "Unknown"),
]
class Winner(models.Model):
name = models.CharField(...)
medal = models.CharField(..., choices=Medal.choices)
sport = models.CharField(..., choices=SPORT_CHOICES)
Django 5.0 では、イテラブルの代わりにマッピングまたは呼び出し可能なものが受け入れられるようになり、 列挙型 を直接展開することで、.choices
の使用が不要になりました。
from django.db import models
Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")
SPORT_CHOICES = { # Using a mapping instead of a list of 2-tuples.
"Martial Arts": {"judo": "Judo", "karate": "Karate"},
"Racket": {"badminton": "Badminton", "tennis": "Tennis"},
"unknown": "Unknown",
}
def get_scores():
return [(i, str(i)) for i in range(10)]
class Winner(models.Model):
name = models.CharField(...)
medal = models.CharField(..., choices=Medal) # Using `.choices` not required.
sport = models.CharField(..., choices=SPORT_CHOICES)
score = models.IntegerField(choices=get_scores) # A callable is allowed.
内部的には、 choices
の値が更新されるたびに、渡された choices
が標準形式として 2 タプルのリストに正規化されます。 詳細については、 choices に関するモデルフィールドのリファレンス を確認してください。
マイナーな機能¶
django.contrib.admin
¶
AdminSite.get_log_entries()
メソッドが追加され、サイトのリストされたログエントリのクエリセットをカスタマイズすることができるようになりました。django.contrib.admin.AllValuesFieldListFilter
、ChoicesFieldListFilter
、RelatedFieldListFilter
、およびRelatedOnlyFieldListFilter
の管理フィルタは、複数の値を持つクエリパラメータを扱えるようになりました。XRegExp
がバージョン 3.2.0 から 5.1.1 にアップグレードされました。- 指定されたモデルの管理クラスを返す
AdminSite.get_model_admin()
メソッドが追加されました。 ModelAdmin.list_display
のプロパティがboolean
属性をサポートするようになりました。- jQuery のバージョンが 3.6.4 から 3.7.1 にアップグレードされました。
django.contrib.auth
¶
- PBKDF2パスワードハッシュにおけるデフォルトの反復回数が、 600,000 から 720,000 に増加しました。
- 以下の新しい非同期関数が、
a
プレフィックスを使用して提供されます:django.contrib.auth.aauthenticate()
、aget_user()
、alogin()
、alogout()
、aupdate_session_auth_hash()
。 AuthenticationMiddleware
に、現在ログインしているユーザーを返す非同期メソッドHttpRequest.auser()
が追加されました。- 新しい
django.contrib.auth.hashers.acheck_password()
非同期関数とAbstractBaseUser.acheck_password()
メソッドにより、ユーザーパスワードの非同期チェックが可能になりました。
django.contrib.contenttypes
¶
QuerySet.prefetch_related()
が、不均一な (non-homogeneous) 結果のセットを含むGenericForeignKey
のプリフェッチをサポートするようになりました。
django.contrib.gis
¶
- 新しい
ClosestPoint()
関数は、他のジオメトリから最も近い、ジオメトリ上の2次元の点を返します。 - GIS aggregates が
filter
引数をサポートするようになりました。 - GDAL 3.7 および GEOS 3.12 のサポートが追加されました。
- 新しい
GEOSGeometry.equals_identical()
メソッドを使用すると、ジオメトリの点単位の等価性チェックが行えるようになります。
django.contrib.messages
¶
response
に追加されたmessages
のテストを行う、アサーションメソッドMessagesTestMixin.assertMessages()
が追加されました。
django.contrib.postgres
¶
ExclusionConstraint
にviolation_error_code
属性が追加され、 オブジェクトの検証 中に発生するValidationError
のcode
をカスタマイズできるようになりました。
非同期ビュー¶
- ASGIを利用中、
http.disconnect
イベントが処理されるようになりました。これにより、ビューは応答が生成される前にクライアントが切断された場合に、必要なクリーンアップを実行できます。詳細については、 切断をハンドリングする を参照してください。
デコレータ¶
- 以下のデコレータが、非同期ビュー関数をサポートするようになりました:
cache_control()
never_cache()
no_append_slash()
csrf_exempt()
csrf_protect()
ensure_csrf_cookie()
requires_csrf_token()
sensitive_variables()
sensitive_post_parameters()
gzip_page()
condition()
conditional_page()
etag()
last_modified()
require_http_methods()
require_GET()
require_POST()
require_safe()
vary_on_cookie()
vary_on_headers()
xframe_options_deny()
xframe_options_sameorigin()
xframe_options_exempt()
Error Reporting¶
sensitive_variables()
およびsensitive_post_parameters()
が、非同期関数とともに使用できるようになりました。
ファイルストレージ¶
File.open()
がすべての位置引数 (*args
) とキーワード引数 (**kwargs
) を Python のビルトイン関数open()
に渡すようになりました。
フォーム¶
URLField
に、デフォルトの URL スキームを指定するassume_scheme
引数が追加されました。- アクセシビリティを向上させるために、以下の変更が行われました:
- フォームフィールドに
aria-describedby
HTML属性が追加され、スクリーンリーダーがフォームフィールドとヘルプテキストを関連付けることができるようになりました。 - 無効なフォームフィールドが
aria-invalid="true"
HTML属性を含むようになりました。
- フォームフィールドに
国際化 (internationalization)¶
- ウイグル語のサポートと翻訳が利用可能になりました。
マイグレーション¶
functools.cache()
またはfunctools.lru_cache()
でデコレーションされた関数のシリアライズが、カスタムのシリアライザーを書く必要なくサポートされるようになりました。
モデル¶
QuerySet.update_or_create()
とQuerySet.aupdate_or_create()
メソッドに、作成操作のために異なるフィールド値を指定できるcreate_defaults
引数が追加されました。BaseConstraint
、CheckConstraint
、およびUniqueConstraint
にviolation_error_code
属性が追加され、 オブジェクトの検証 中に発生するValidationError
のcode
をカスタマイズすることができるようになりました。Model.save()
に force_insert 引数が追加され、挿入を強制する必要がある親クラスのタプルを指定できるようになりました。QuerySet.bulk_create()
メソッドとQuerySet.abulk_create()
メソッドは、update_conflicts
パラメータが有効な場合(データベースがサポートしている場合)、各モデルインスタンスに主キーを設定するようになりました。UniqueConstraint.nulls_distinct
属性が追加され、PostgreSQL 15 以降でのNULL
値の処理をカスタマイズすることができるようになりました。- 非同期的にオブジェクトを取得するショートカット
aget_object_or_404()
とaget_list_or_404()
が追加されました。 - モデルインスタンスの先読みを非同期的に行う
aprefetch_related_objects()
関数が追加されました。 QuerySet.aiterator()
が以前のprefetch_related()
呼び出しをサポートするようになりました。- MariaDB 10.7 以降で、
UUIDField
はCHAR(32)
ではなくUUID
カラムとして作成されます。詳細は、 MariaDB 10.7+ における既存の UUIDField のマイグレーション のマイグレーションガイドを参照してください。 - Djangoは現在、 oracledb バージョン 1.3.2 以上をサポートしています。今回のリリースで
cx_Oracle
のサポートは非推奨となり、Django 6.0 で削除されます。
ページネーション¶
django.core.paginator.Paginator.error_messages
引数が追加され、Paginator.page()
が送出するエラーメッセージをカスタマイズできるようになりました。
シグナル¶
- 新しい
Signal.asend()
およびSignal.asend_robust()
メソッドが非同期のシグナルディスパッチに対応しました。シグナルのレシーバーは同期または非同期のどちらにも対応し、正しい呼び出しスタイルに自動的に適応します。
テスト¶
Client
とAsyncClient
において、a
プレフィックスを持つ以下の非同期メソッドが提供されるようになりました:asession()
、alogin()
、aforce_login()
、alogout()
。AsyncClient
がfollow
パラメータをサポートするようになりました。- Python 3.12 以降、
test --durations
オプションを指定することで、最も遅いテストの実行時間を表示できるようになりました。
バリデータ¶
StepValueValidator
にoffset
引数が追加され、有効な値のオフセットを指定できるようになりました。
5.0 での後方互換性のない変更¶
データベースバックエンド API¶
このセクションでは、サードパーティのデータベースバックエンドで必要になる可能性のある変更について説明します。
- データベースがデフォルトでデータベース関数をサポートしていない場合、
DatabaseFeatures.supports_expression_defaults
をFalse
に設定する必要があります。 - データベースが
INSERT
クエリ内でDEFAULT
キーワードをサポートしていない場合、DatabaseFeatures.supports_default_keyword_in_insert
をFalse
に設定する必要があります。 - データベースがバルク
INSERT
クエリ内でDEFAULT
キーワードをサポートしていない場合、DatabaseFeatures.supports_default_keyword_in_bulk_insert
をFalse
に設定する必要があります。
django.contrib.gis
¶
- GDAL 2.2 および 2.3 のサポートが削除されました。
- GEOS 3.6 および 3.7 のサポートが削除されました。
django.contrib.sitemaps
¶
- Google Sitemaps の ping エンドポイントが非推奨となり、2024年1月に削除されるため、
django.contrib.sitemaps.ping_google()
関数とping_google
管理コマンドは削除されました。 django.contrib.sitemaps.SitemapNotFound
例外クラスは削除されました。
MySQL < 8.0.11 のサポートを廃止しました。¶
MySQL 8.0.x シリーズのプレリリース版のサポートが削除されました。Django 5.0 は MySQL 8.0.11 以上をサポートします。
QuerySet.update_or_create()
を使用する際に、create_defaults__exact
を必要とする場合があります。¶
QuerySet.update_or_create()
は、パラメータ create_defaults
をサポートするようになりました。その結果、update_or_create()
で使用される create_defaults
という名前のフィールドを持つモデルは、ルックアップで create_defaults__exact
を指定する必要があります。
MariaDB 10.7+ における既存の UUIDField
のマイグレーション¶
MariaDB 10.7以降では、UUIDField
は CHAR(32)
カラムではなく UUID
カラムとして作成されるようになりました。その結果、Django < 5.0で作成された任意の UUIDField
は、CHAR(32)
に基づく UUIDField
サブクラスに置き換える必要があります:
class Char32UUIDField(models.UUIDField):
def db_type(self, connection):
return "char(32)"
def get_db_prep_value(self, value, connection, prepared=False):
value = super().get_db_prep_value(value, connection, prepared)
if value is not None:
value = value.hex
return value
例:
class MyModel(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
これは以下のようにすべきです:
class Char32UUIDField(models.UUIDField): ...
class MyModel(models.Model):
uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)
makemigrations
コマンドを実行すると、何も行わない AlterField
操作を含むマイグレーションが生成されます。
その他¶
- ドキュメント化されていない
BaseModelFormSet.save_existing()
メソッドのinstance
引数がobj
に名前変更されました。 - ドキュメント化されていない
django.contrib.admin.helpers.checkbox
が削除されました。 - SQLite 上での Integer フィールドは、
sqlite3
の動作に合わせ、64 ビット整数としてバリデーションされるようになりました。 - ドキュメント化されていない
Query.annotation_select_mask
属性が、文字列のセットから順序付きの文字列リストに変更されました。 width_field
とheight_field
が設定されていない場合、post_init
シグナル上でImageField.update_dimension_fields()
が呼び出されなくなりました。Now
データベース関数は、Oracle上でCURRENT_TIMESTAMP
の代わりにLOCALTIMESTAMP
を使用するようになりました。AdminSite.site_header
は、<h1>
タグの代わりに<div>
タグでレンダリングされるようになりました。スクリーンリーダーを使用するユーザーは、ページ内のナビゲーションに見出し要素に依存しています。<h1>
要素が2つあると混乱を招き、サイトヘッダーはすべてのページで繰り返されるため、これは役に立たないものでした。- アクセシビリティを向上させるために、admin サイトのメインコンテンツエリアとヘッダーコンテンツエリアは、
<div>
の代わりに<main>
と<header>
タグでレンダリングされるようになりました。 - SQLの
XOR
演算子をネイティブサポートしていないデータベースでは、排他的論理和 (XOR
) 演算子^
が、ちょうど1つのオペランドではなく、奇数個のオペランドがマッチする行を返すようになりました。これは、MySQL、MariaDB、およびPythonの動作と一致しています。 asgiref
の最小サポートバージョンが 3.6.0 から 3.7.0 に引き上げられました。selenium
の最小サポートバージョンが 3.8.0 から 4.8.0 に引き上げられました。AlreadyRegistered
およびNotRegistered
例外がdjango.contrib.admin.sites
からdjango.contrib.admin.exceptions
に移動されました。- SQLite の最小サポートバージョンが 3.21.0 から 3.27.0 に引き上げられました。
cx_Oracle
< 8.3 のサポートが削除されました。- アプリレジストリが完全に満たされる前にSQLクエリを実行すると、
RuntimeWarning
が発生するようになりました。 - 非 UTF-8 エンコードのリクエストに対しては、application/x-www-form-urlencoded コンテンツタイプで
BadRequest
が発生します。詳細については、RFC 1866 を参照してください。 - colorama の最低サポートバージョンが 0.4.6 に引き上げられました。
docutils
の最低サポートバージョンが 0.19 に引き上げられました。- オーバーフローする整数に対するクエリセットのフィルタリングが、常にからのクエリセットを返すようになりました。結果として、そのような場合には整数フィールドに対する算術演算子を 明示的にラップする ために、
ExpressionWrapper()
を使用する必要があるかもしれません。
5.0 で非推奨となった機能¶
その他¶
DjangoDivFormRenderer
とJinja2DivFormRenderer
トランジショナルフォームレンダラーが非推奨になりました。- 位置引数
name
およびviolation_error_message
をBaseConstraint
に渡す方法は、キーワード専用引数を使用する方法に変更されるため、非推奨となりました。 request
がModelAdmin.lookup_allowed()
のシグネチャに追加されました。この引数を受け入れないModelAdmin
のサブクラスのサポートは非推奨です。ForeignObject
とForeignObjectRel
のget_joining_columns()
メソッドは非推奨です。Django 6.0 から、django.db.models.sql.datastructures.Join
はget_joining_columns()
へのフォールバックを行わなくなります。サブクラスでは代わりにget_joining_fields()
を実装するべきです。ForeignObject.get_reverse_joining_columns()
メソッドは非推奨になりました。forms.URLField
のデフォルトスキームは Django 6.0 で"http"
から"https"
に変更されます。Django 5.x リリースサイクル中に"https"
を想定するようにするには、移行用設定であるFORMS_URLFIELD_ASSUME_HTTPS
をTrue
に設定してください。FORMS_URLFIELD_ASSUME_HTTPS
移行用設定は非推奨になりました。format_html()
の引数やキーワード引数なしでの呼び出しのサポートは削除されます。cx_Oracle
のサポートは非推奨となり、代わりに oracledb 1.3.2+ Python ドライバが推奨されます。DatabaseOperations.field_cast_sql()
はDatabaseOperations.lookup_cast()
に置き換えられました。Django 6.0 からは、BuiltinLookup.process_lhs()
はfield_cast_sql()
を呼び出さなくなります。サードパーティ製のデータベースバックエンドは、代わりにlookup_cast()
を実装すべきです。django.db.models.enums.ChoicesMeta
メタクラスはChoicesType
に名前が変更されました。Prefetch.get_current_queryset()
メソッドは非推奨になりました。- 関係マネージャーとディスクリプタの
get_prefetch_queryset()
メソッドは非推奨になりました。Django 6.0 から、get_prefetcher()
とprefetch_related_objects()
はget_prefetch_queryset()
にフォールバックしなくなります。サブクラスでは代わりにget_prefetch_querysets()
を実装するべきです。
5.0 で削除された機能¶
以下の機能は、非推奨サイクルの終わりに達したため、Django 5.0 で削除されます。
詳しくは Features deprecated in 4.0 を見てください。ここには、プロジェクトからこれらの機能を削除する方法についても書かれています。
SERIALIZE
テスト設定が削除されました。- ドキュメント化されていなかった
django.utils.baseconv
モジュールが削除されました。 - ドキュメント化されていなかった
django.utils.datetime_safe
モジュールが削除されました。 USE_TZ
設定のデフォルト値がFalse
からTrue
に変更されました。- リクエストコンテキストの外部で生成されるサイトマップのデフォルトのプロトコルが
'http'
から'https'
に変更されました。 DiscoverRunner.build_suite()
およびDiscoverRunner.run_tests()
のextra_tests
引数が削除されました。django.contrib.postgres.aggregates.ArrayAgg
、JSONBAgg
、StringAgg
aggregates が、行がない場合にそれぞれ[]
、[]
、''
を返さなくなりました。USE_L10N
設定が削除されました。USE_DEPRECATED_PYTZ
移行用設定が削除されました。pytz
タイムゾーンに対するサポートが削除されました。- 以下から、
is_dst
引数が削除されました。QuerySet.datetimes()
django.utils.timezone.make_aware()
django.db.models.functions.Trunc()
django.db.models.functions.TruncSecond()
django.db.models.functions.TruncMinute()
django.db.models.functions.TruncHour()
django.db.models.functions.TruncDay()
django.db.models.functions.TruncWeek()
django.db.models.functions.TruncMonth()
django.db.models.functions.TruncQuarter()
django.db.models.functions.TruncYear()
django.contrib.gis.admin.GeoModelAdmin
およびOSMGeoAdmin
クラスが削除されました。- ドキュメント化されていなかった
BaseForm._html_output()
メソッドが削除されました。 ErrorDict
とErrorList
をレンダリングする際に、SafeString
ではなくstr
を返す機能が削除されました。
これらの変更の詳細、およびこれらの機能の使用を取り除く方法については、Features deprecated in 4.1 を参照してください。
SitemapIndexItem.__str__()
メソッドが削除されました。CSRF_COOKIE_MASKED
移行用設定が削除されました。django.utils.functional.cached_property()
のname
引数が削除されました。django.contrib.postgres.constraints.ExclusionConstraint
のopclasses
引数が削除されました。- ドキュメント化されていなかった、
SimpleTestCase.assertFormError()
およびassertFormsetError()
にerrors=None
を渡せる機能が削除されました。 django.contrib.sessions.serializers.PickleSerializer
が削除されました。- リレーション先オブジェクトをプリフェッチするクエリセットに対して、
chunk_size
引数を提供せずにQuerySet.iterator()
を使うことはできなくなりました。 - 未保存のモデルインスタンスを関連フィルターに渡すことはできなくなりました。
RemoteUserBackend.configure_user()
サブクラスのシグネチャにはcreated=True
が必要になりました。django.contrib.auth.views.LogoutView
およびdjango.contrib.auth.views.logout_then_login()
における、GET
リクエスト経由のログアウトのサポートが削除されました。datetime.timezone.utc
へのdjango.utils.timezone.utc
エイリアスが削除されました。SimpleTestCase.assertFormError()
およびassertFormSetError()
にレスポンスオブジェクトとフォーム/フォームセット名を渡すことはできなくなりました。django.contrib.gis.admin.OpenLayersWidget
が削除されました。
django.contrib.auth.hashers.CryptPasswordHasher
が削除されました。
"django/forms/default.html"
および"django/forms/formsets/default.html"
テンプレートが削除されました。- デフォルトの form および formset のレンダリングスタイルが div ベースに変更されました。
Expression.asc()
とExpression.desc()
メソッド、およびOrderBy
式にnulls_first=False
またはnulls_last=False
を渡すことはできなくなりました。