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イベントが処理されるようになりました。これにより、ビューは応答が生成される前にクライアントが切断された場合に、必要なクリーンアップを実行できます。詳細については、 切断をハンドリングする を参照してください。
デコレータ¶
以下のデコレータが、非同期ビュー関数をサポートするようになりました:
conditional_page()xframe_options_deny()xframe_options_sameorigin()xframe_options_exempt()
エラー報告¶
sensitive_variables()およびsensitive_post_parameters()が、非同期関数とともに使用できるようになりました。
ファイルストレージ¶
File.open()がすべての位置引数 (*args) とキーワード引数 (**kwargs) を Python のビルトイン関数open()に渡すようになりました。
フォーム¶
URLFieldに、デフォルトの URL スキームを指定するassume_scheme引数が追加されました。アクセシビリティを向上させるために、以下の変更が行われました:
フォームフィールドに
aria-describedbyHTML属性が追加され、スクリーンリーダーがフォームフィールドとヘルプテキストを関連付けることができるようになりました。無効なフォームフィールドが
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パラメータをサポートするようになりました。DiscoverRunnernow allows showing the duration of the slowest tests using thetest --durationsoption (available on Python 3.12+).
バリデータ¶
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、StringAggaggregates が、行がない場合にそれぞれ[]、[]、''を返さなくなりました。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を渡すことはできなくなりました。