kopia lustrzana https://github.com/wagtail/wagtail
Fix - Ensure `WagtailAdminFormPageForm.clean` works for any related name
Dynamically detect the `related_name` of any form fields attached to the page so that validation is actually run for custom related_names. This also will apply validation even if there are multiple `AbstractFormField` subclasses related to the page. Add unit test to ensure that duplicate clean name validation correctly runs on FormPage models with a custom related name. Originally from #10375pull/12536/head
rodzic
9d31fd3fa5
commit
281efdbc88
|
@ -173,17 +173,34 @@ class SelectDateForm(django.forms.Form):
|
|||
|
||||
class WagtailAdminFormPageForm(WagtailAdminPageForm):
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
related_name = "form_fields"
|
||||
"""
|
||||
Dynamically detect all related AbstractFormField subclasses to ensure
|
||||
validation is applied regardless of the related_name or if there are multiple
|
||||
AbstractFormField subclasses related to this page.
|
||||
"""
|
||||
|
||||
from .models import AbstractFormField
|
||||
|
||||
cleaned_data = super().clean()
|
||||
|
||||
form_fields_related_names = [
|
||||
related_object.related_name
|
||||
for related_object in self.instance._meta.related_objects
|
||||
if issubclass(related_object.related_model, AbstractFormField)
|
||||
]
|
||||
|
||||
for related_name in form_fields_related_names:
|
||||
if related_name not in self.formsets:
|
||||
continue
|
||||
|
||||
# Check for duplicate form fields by comparing their internal clean_names
|
||||
if "form_fields" in self.formsets:
|
||||
forms = self.formsets[related_name].forms
|
||||
for form in forms:
|
||||
form.is_valid()
|
||||
|
||||
# Use existing clean_name or generate for new fields.
|
||||
# clean_name is set in FormField.save
|
||||
# Use existing clean_name or generate for new fields,
|
||||
# raise an error if there are duplicate resolved clean names.
|
||||
# Note: `clean_name` is set in `FormField.save`.
|
||||
|
||||
clean_names = [
|
||||
f.instance.clean_name or f.instance.get_field_clean_name()
|
||||
for f in forms
|
||||
|
|
|
@ -1973,6 +1973,52 @@ class TestDuplicateFormFieldLabels(WagtailTestUtils, TestCase):
|
|||
text="There is another field with the label Test field, please change one of them.",
|
||||
)
|
||||
|
||||
def test_adding_duplicate_form_labels_with_custom_related_name(self):
|
||||
"""
|
||||
Ensure duplicate field names are checked, even if a custom related_name is used.
|
||||
``FormPageWithCustomSubmission`` uses the related_name `custom_form_fields`.
|
||||
"""
|
||||
|
||||
post_data = {
|
||||
"title": "Drink selection",
|
||||
"content": "Some content",
|
||||
"slug": "drink-selection",
|
||||
"custom_form_fields-TOTAL_FORMS": "3",
|
||||
"custom_form_fields-INITIAL_FORMS": "3",
|
||||
"custom_form_fields-MIN_NUM_FORMS": "0",
|
||||
"custom_form_fields-MAX_NUM_FORMS": "1000",
|
||||
# Duplicate field labels
|
||||
"custom_form_fields-0-id": "",
|
||||
"custom_form_fields-0-label": "chocolate",
|
||||
"custom_form_fields-0-field_type": "singleline",
|
||||
"custom_form_fields-1-id": "",
|
||||
"custom_form_fields-1-label": "chocolate",
|
||||
"custom_form_fields-1-field_type": "singleline",
|
||||
# Unique field label
|
||||
"custom_form_fields-2-id": "",
|
||||
"custom_form_fields-2-label": "coffee",
|
||||
"custom_form_fields-2-field_type": "singleline",
|
||||
}
|
||||
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=(
|
||||
"tests",
|
||||
"formpagewithcustomsubmission",
|
||||
self.root_page.id,
|
||||
),
|
||||
),
|
||||
post_data,
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
self.assertContains(
|
||||
response,
|
||||
text="There is another field with the label chocolate, please change one of them.",
|
||||
)
|
||||
|
||||
|
||||
class TestPreview(WagtailTestUtils, TestCase):
|
||||
post_data = {
|
||||
|
|
Ładowanie…
Reference in New Issue