2023年12月4日
Django 5.0 へようこそ!
このリリースノートでは、 バージョン 5.0 の新機能 と、Django 4.2 以前からアップグレードする際に注意すべき、 後方互換性のない変更 について説明します。また、 一部の機能を非推奨 としました。
既存のプロジェクトをアップデートするときは、 Django の新しいバージョンへの更新 ガイドに従ってください。
Django 5.0 は Python 3.10、3.11、および3.12をサポートしています。各バージョン系列の最終リリースのみが公式にサポートされるので、そのいずれかを使用することを 強く推奨 します。
Django 4.2.x シリーズは Python 3.8 と 3.9 をサポートする最後のバージョンになります。
Django 5.0 リリース後は、サードパーティアプリの開発者は 4.2 より前のバージョンの Django のサポートを終了することを推奨します。このとき、python -Wd を使ったパッケージテストを実行して、廃止予定 (deprecation) の警告を出力できます。廃止予定の警告が出ないように修正すれば、アプリケーションは 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 属性をサポートするようになりました。django.contrib.auth¶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次元の点を返します。filter 引数をサポートするようになりました。GEOSGeometry.equals_identical() メソッドを使用すると、ジオメトリの点単位の等価性チェックが行えるようになります。django.contrib.messages¶response に追加された messages のテストを行う、アサーションメソッド MessagesTestMixin.assertMessages() が追加されました。django.contrib.postgres¶ExclusionConstraint に violation_error_code 属性が追加され、 オブジェクトの検証 中に発生する ValidationError の code をカスタマイズできるようになりました。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()sensitive_variables() および sensitive_post_parameters() が、非同期関数とともに使用できるようになりました。File.open() がすべての位置引数 (*args) とキーワード引数 (**kwargs) を Python のビルトイン関数 open() に渡すようになりました。URLField に、デフォルトの URL スキームを指定する assume_scheme 引数が追加されました。aria-describedby HTML属性が追加され、スクリーンリーダーがフォームフィールドとヘルプテキストを関連付けることができるようになりました。aria-invalid="true" HTML属性を含むようになりました。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() 呼び出しをサポートするようになりました。UUIDField は CHAR(32) ではなく UUID カラムとして作成されます。詳細は、 MariaDB 10.7+ における既存の UUIDField のマイグレーション のマイグレーションガイドを参照してください。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 パラメータをサポートするようになりました。test --durations オプションを指定することで、最も遅いテストの実行時間を表示できるようになりました。StepValueValidator に offset 引数が追加され、有効な値のオフセットを指定できるようになりました。このセクションでは、サードパーティのデータベースバックエンドで必要になる可能性のある変更について説明します。
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¶django.contrib.sitemaps¶django.contrib.sitemaps.ping_google() 関数と ping_google 管理コマンドは削除されました。django.contrib.sitemaps.SitemapNotFound 例外クラスは削除されました。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 を指定する必要があります。
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 が削除されました。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つあると混乱を招き、サイトヘッダーはすべてのページで繰り返されるため、これは役に立たないものでした。<div> の代わりに <main> と <header> タグでレンダリングされるようになりました。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 に移動されました。cx_Oracle < 8.3 のサポートが削除されました。RuntimeWarning が発生するようになりました。BadRequest が発生します。詳細については、RFC 1866 を参照してください。docutils の最低サポートバージョンが 0.19 に引き上げられました。ExpressionWrapper() を使用する必要があるかもしれません。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() を実装するべきです。以下の機能は、非推奨サイクルの終わりに達したため、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" テンプレートが削除されました。Expression.asc() と Expression.desc() メソッド、および OrderBy 式に nulls_first=False または nulls_last=False を渡すことはできなくなりました。8月 06, 2024