Django 5.0 リリースノートLink to this heading

2023年12月4日

Django 5.0 へようこそ!

このリリースノートでは、 バージョン 5.0 の新機能 と、Django 4.2 以前からアップグレードする際に注意すべき、 後方互換性のない変更 について説明します。また、 一部の機能を非推奨 としました。

既存のプロジェクトをアップデートするときは、 Django の新しいバージョンへの更新 ガイドに従ってください。

Python バージョン間の互換性Link to this heading

Django 5.0 は Python 3.10、3.11、および3.12をサポートしています。各バージョン系列の最終リリースのみが公式にサポートされるので、そのいずれかを使用することを 強く推奨 します。

Django 4.2.x シリーズは Python 3.8 と 3.9 をサポートする最後のバージョンになります。

古いバージョンの Django をサポートするサードパーティのライブラリLink to this heading

Django 5.0 リリース後は、サードパーティアプリの開発者は 4.2 より前のバージョンの Django のサポートを終了することを推奨します。このとき、python -Wd を使ったパッケージテストを実行して、廃止予定 (deprecation) の警告を出力できます。廃止予定の警告が出ないように修正すれば、アプリケーションは Django 5.0 と互換性のある状態になっているはずです。

Django 5.0の新機能Link to this heading

管理サイトのファセットフィルターLink to this heading

適用されたフィルターのファセット数が、UIを介して切り替えられた場合に、管理者の変更リストで表示されるようになりました。この動作は、新しい ModelAdmin.show_facets 属性を介して変更することができます。詳細については、 ファセット (Facet) を参照してください。

フォームフィールドレンダリング用の簡略化されたテンプレートLink to this heading

Django 5.0 から、フィールドグループとフィールドグループテンプレートの概念が導入されます。これにより、Djangoフォームフィールドの関連要素(ラベル、ウィジェット、ヘルプテキスト、エラーなど)のレンダリングが簡略化されます。

たとえば、以下のテンプレートがあるとします。

Django template
<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>

これを、以下のように簡略化できるようになりました:

Django template
<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" テンプレートでフィールドをレンダリングします。プロジェクト、フィールド、またはリクエストごとにカスタマイズできます。詳しくは 再利用可能なフィールドグループテンプレート を参照してください。

データベースで計算されたデフォルト値Link to this heading

新しい Field.db_default パラメータは、データベースで計算されるデフォルト値を設定します。次に例を示します。

Code
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())

データベースで生成されるモデルフィールドLink to this heading

新しい GeneratedField により、データベースで生成されるカラムを作成することが可能になりました。このフィールドは、他のフィールドから常に計算されるフィールドを作成するので、すべてのサポートされているデータベースバックエンドで使用することができます。次に例を示します。

Code
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,
    )

フィールドの選択肢を宣言する際のオプションが増加Link to this heading

Field.choices (モデルフィールド用)ChoiceField.choices (フォームフィールド用) により、値を宣言する際の柔軟性が向上しました。以前のバージョンの Django では、 choices は 2 タプルのリストか、 列挙型 のサブクラスである必要がありましたが、後者の場合、 .choices 属性にアクセスして、期待される形式で値を提供する必要がありました:

Code
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 の使用が不要になりました。

Code
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 に関するモデルフィールドのリファレンス を確認してください。

マイナーな機能Link to this heading

django.contrib.adminLink to this heading

  • AdminSite.get_log_entries() メソッドが追加され、サイトのリストされたログエントリのクエリセットをカスタマイズすることができるようになりました。

  • django.contrib.admin.AllValuesFieldListFilterChoicesFieldListFilterRelatedFieldListFilter 、および 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.authLink to this heading

django.contrib.contenttypesLink to this heading

django.contrib.gisLink to this heading

  • 新しい ClosestPoint() 関数は、他のジオメトリから最も近い、ジオメトリ上の2次元の点を返します。

  • GIS aggregatesfilter 引数をサポートするようになりました。

  • GDAL 3.7 および GEOS 3.12 のサポートが追加されました。

  • 新しい GEOSGeometry.equals_identical() メソッドを使用すると、ジオメトリの点単位の等価性チェックが行えるようになります。

django.contrib.messagesLink to this heading

django.contrib.postgresLink to this heading

非同期ビューLink to this heading

  • ASGIを利用中、 http.disconnect イベントが処理されるようになりました。これにより、ビューは応答が生成される前にクライアントが切断された場合に、必要なクリーンアップを実行できます。詳細については、 切断をハンドリングする を参照してください。

デコレータLink to this heading

エラー報告Link to this heading

ファイルストレージLink to this heading

  • File.open() がすべての位置引数 (*args) とキーワード引数 (**kwargs) を Python のビルトイン関数 open() に渡すようになりました。

フォームLink to this heading

  • URLField に、デフォルトの URL スキームを指定する assume_scheme 引数が追加されました。

  • アクセシビリティを向上させるために、以下の変更が行われました:

    • フォームフィールドに aria-describedby HTML属性が追加され、スクリーンリーダーがフォームフィールドとヘルプテキストを関連付けることができるようになりました。

    • 無効なフォームフィールドが aria-invalid="true" HTML属性を含むようになりました。

国際化 (internationalization)Link to this heading

  • ウイグル語のサポートと翻訳が利用可能になりました。

マイグレーションLink to this heading

  • functools.cache() または functools.lru_cache() でデコレーションされた関数のシリアライズが、カスタムのシリアライザーを書く必要なくサポートされるようになりました。

モデルLink to this heading

ページネーションLink to this heading

シグナルLink to this heading

  • 新しい Signal.asend() および Signal.asend_robust() メソッドが非同期のシグナルディスパッチに対応しました。シグナルのレシーバーは同期または非同期のどちらにも対応し、正しい呼び出しスタイルに自動的に適応します。

テンプレートLink to this heading

  • シーケンスの各要素に escape を適用する escapeseq テンプレートフィルタが追加されました。

テストLink to this heading

バリデータLink to this heading

  • StepValueValidatoroffset 引数が追加され、有効な値のオフセットを指定できるようになりました。

5.0 での後方互換性のない変更Link to this heading

データベースバックエンド APILink to this heading

このセクションでは、サードパーティのデータベースバックエンドで必要になる可能性のある変更について説明します。

  • データベースがデフォルトでデータベース関数をサポートしていない場合、DatabaseFeatures.supports_expression_defaultsFalse に設定する必要があります。

  • データベースが INSERT クエリ内で DEFAULT キーワードをサポートしていない場合、DatabaseFeatures.supports_default_keyword_in_insertFalse に設定する必要があります。

  • データベースがバルク INSERT クエリ内で DEFAULT キーワードをサポートしていない場合、DatabaseFeatures.supports_default_keyword_in_bulk_insertFalse に設定する必要があります。

django.contrib.gisLink to this heading

  • GDAL 2.2 および 2.3 のサポートが削除されました。

  • GEOS 3.6 および 3.7 のサポートが削除されました。

django.contrib.sitemapsLink to this heading

  • Google Sitemaps の ping エンドポイントが非推奨となり、2024年1月に削除されるため、django.contrib.sitemaps.ping_google() 関数と ping_google 管理コマンドは削除されました。

  • django.contrib.sitemaps.SitemapNotFound 例外クラスは削除されました。

MySQL < 8.0.11 のサポートを廃止しました。Link to this heading

MySQL 8.0.x シリーズのプレリリース版のサポートが削除されました。Django 5.0 は MySQL 8.0.11 以上をサポートします。

QuerySet.update_or_create() を使用する際に、create_defaults__exact を必要とする場合があります。Link to this heading

QuerySet.update_or_create() は、パラメータ create_defaults をサポートするようになりました。その結果、update_or_create() で使用される create_defaults という名前のフィールドを持つモデルは、ルックアップで create_defaults__exact を指定する必要があります。

MariaDB 10.7+ における既存の UUIDField のマイグレーションLink to this heading

MariaDB 10.7以降では、UUIDFieldCHAR(32) カラムではなく UUID カラムとして作成されるようになりました。その結果、Django < 5.0で作成された任意の UUIDField は、CHAR(32) に基づく UUIDField サブクラスに置き換える必要があります:

Code
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

例:

Code
class MyModel(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)

これは以下のようにすべきです:

Code
class Char32UUIDField(models.UUIDField): ...


class MyModel(models.Model):
    uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)

makemigrations コマンドを実行すると、何も行わない AlterField 操作を含むマイグレーションが生成されます。

その他Link to this heading

  • ドキュメント化されていない BaseModelFormSet.save_existing() メソッドの instance 引数が obj に名前変更されました。

  • ドキュメント化されていない django.contrib.admin.helpers.checkbox が削除されました。

  • SQLite 上での Integer フィールドは、sqlite3 の動作に合わせ、64 ビット整数としてバリデーションされるようになりました。

  • ドキュメント化されていない Query.annotation_select_mask 属性が、文字列のセットから順序付きの文字列リストに変更されました。

  • width_fieldheight_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 で非推奨となった機能Link to this heading

その他Link to this heading

  • DjangoDivFormRendererJinja2DivFormRenderer トランジショナルフォームレンダラーが非推奨になりました。

  • 位置引数 name および violation_error_messageBaseConstraint に渡す方法は、キーワード専用引数を使用する方法に変更されるため、非推奨となりました。

  • requestModelAdmin.lookup_allowed() のシグネチャに追加されました。この引数を受け入れない ModelAdmin のサブクラスのサポートは非推奨です。

  • ForeignObjectForeignObjectRelget_joining_columns() メソッドは非推奨です。Django 6.0 から、django.db.models.sql.datastructures.Joinget_joining_columns() へのフォールバックを行わなくなります。サブクラスでは代わりに get_joining_fields() を実装するべきです。

  • ForeignObject.get_reverse_joining_columns() メソッドは非推奨になりました。

  • forms.URLField のデフォルトスキームは Django 6.0 で "http" から "https" に変更されます。Django 5.x リリースサイクル中に "https" を想定するようにするには、移行用設定である FORMS_URLFIELD_ASSUME_HTTPSTrue に設定してください。

  • 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 で削除された機能Link to this heading

以下の機能は、非推奨サイクルの終わりに達したため、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.ArrayAggJSONBAggStringAgg 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() メソッドが削除されました。

  • ErrorDictErrorList をレンダリングする際に、SafeString ではなく str を返す機能が削除されました。

これらの変更の詳細、およびこれらの機能の使用を取り除く方法については、Features deprecated in 4.1 を参照してください。

  • SitemapIndexItem.__str__() メソッドが削除されました。

  • CSRF_COOKIE_MASKED 移行用設定が削除されました。

  • django.utils.functional.cached_property()name 引数が削除されました。

  • django.contrib.postgres.constraints.ExclusionConstraintopclasses 引数が削除されました。

  • ドキュメント化されていなかった、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 を渡すことはできなくなりました。