Fix formfield_callback handling for Django 4.2a0

As of e03cdf76e7, formfield_callback can be set through ModelForm.meta. This new mechanism was overriding our metaclass hacking for WagtailAdminModelForm to accomplish the same thing, and as a result the custom Wagtail admin form fields were reverting to the Django defaults. We therefore need to update WagtailAdminModelForm to use the new mechanism when on Django >=4.2.
pull/9206/head
Matt Westcott 2022-08-19 15:11:08 +01:00 zatwierdzone przez LB (Ben Johnston)
rodzic e46991ffbe
commit 0fd2d3d4c1
3 zmienionych plików z 26 dodań i 16 usunięć
docs/releases
wagtail/admin/forms

Wyświetl plik

@ -28,6 +28,7 @@ Changelog
* Fix: Revise colour usage so that privacy & locked indicators can be seen in Windows High Contrast mode (LB (Ben Johnston))
* Fix: Ensure that disabled buttons have a consistent presentation on hover to indicate no interaction is available (Paarth Agarwal)
* Fix: Update the 'Locked pages' report menu title so that it is consistent with other pages reports and its own title on viewing (Nicholas Johnson)
* Fix: Support `formfield_callback` handling on `ModelForm.Meta` for future Django 4.2 release (Matt Westcott)
4.0.2 (xx.xx.xxxx) - IN DEVELOPMENT

Wyświetl plik

@ -40,6 +40,7 @@ Wagtail 4.1 is designated a Long Term Support (LTS) release. Long Term Support r
* Revise colour usage so that privacy & locked indicators can be seen in Windows High Contrast mode (LB (Ben Johnston))
* Ensure that disabled buttons have a consistent presentation on hover to indicate no interaction is available (Paarth Agarwal)
* Update the 'Locked pages' report menu title so that it is consistent with other pages reports and its own title on viewing (Nicholas Johnson)
* Support `formfield_callback` handling on `ModelForm.Meta` for future Django 4.2 release (Matt Westcott)
## Upgrade considerations

Wyświetl plik

@ -1,5 +1,6 @@
import copy
from django import VERSION as DJANGO_VERSION
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from modelcluster.forms import ClusterForm, ClusterFormMetaclass, ClusterFormOptions
@ -100,25 +101,27 @@ class WagtailAdminModelFormOptions(PermissionedFormOptionsMixin, ClusterFormOpti
class WagtailAdminModelFormMetaclass(PermissionedFormMetaclass, ClusterFormMetaclass):
options_class = WagtailAdminModelFormOptions
# Override the behaviour of the regular ModelForm metaclass -
# which handles the translation of model fields to form fields -
# to use our own formfield_for_dbfield function to do that translation.
# This is done by sneaking a formfield_callback property into the class
# being defined (unless the class already provides a formfield_callback
# of its own).
# while we're at it, we'll also set extra_form_count to 0, as we're creating
# extra forms in JS
# set extra_form_count to 0, as we're creating extra forms in JS
extra_form_count = 0
def __new__(cls, name, bases, attrs):
if "formfield_callback" not in attrs or attrs["formfield_callback"] is None:
attrs["formfield_callback"] = formfield_for_dbfield
if DJANGO_VERSION < (4, 2):
new_class = super(WagtailAdminModelFormMetaclass, cls).__new__(
cls, name, bases, attrs
)
return new_class
def __new__(cls, name, bases, attrs):
# Override the behaviour of the regular ModelForm metaclass -
# which handles the translation of model fields to form fields -
# to use our own formfield_for_dbfield function to do that translation.
# This is done by sneaking a formfield_callback property into the class
# being defined (unless the class already provides a formfield_callback
# of its own).
# As of Django 4.2, formfield_callback is available as an option in ModelForm.Meta
# so we don't have to hack the metaclass for this.
if "formfield_callback" not in attrs or attrs["formfield_callback"] is None:
attrs["formfield_callback"] = formfield_for_dbfield
new_class = super(WagtailAdminModelFormMetaclass, cls).__new__(
cls, name, bases, attrs
)
return new_class
@classmethod
def child_form(cls):
@ -133,6 +136,11 @@ class WagtailAdminModelForm(
self.for_user = kwargs.get("for_user")
super().__init__(*args, **kwargs)
if DJANGO_VERSION >= (4, 2):
class Meta:
formfield_callback = formfield_for_dbfield
# Now, any model forms built off WagtailAdminModelForm instead of ModelForm should pick up
# the nice form fields defined in FORM_FIELD_OVERRIDES.