From 96f9ebe3f6846099641e4b2d49e3e8f9f34aea59 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 28 Feb 2025 00:12:31 +0000 Subject: [PATCH] Recognise required_on_save flag being set on model fields It is clear from the test models and bakerydemo that title is frequently declared with a plain FieldPanel rather than TitleFieldPanel, so we should not rely on the presence of TitleFieldPanel or an explicit required_on_save flag on the FieldPanel to enforce form-level validation on the title. --- wagtail/admin/panels/field_panel.py | 18 ++++++++++++++++-- wagtail/admin/panels/title_field_panel.py | 1 - wagtail/models/pages.py | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/wagtail/admin/panels/field_panel.py b/wagtail/admin/panels/field_panel.py index 0f592f5e8e..4b446230c8 100644 --- a/wagtail/admin/panels/field_panel.py +++ b/wagtail/admin/panels/field_panel.py @@ -25,7 +25,7 @@ class FieldPanel(Panel): disable_comments=None, permission=None, read_only=False, - required_on_save=False, + required_on_save=None, **kwargs, ): super().__init__(**kwargs) @@ -55,7 +55,21 @@ class FieldPanel(Panel): opts = { "fields": [self.field_name], } - if not self.required_on_save: + + required_on_save = self.required_on_save + if required_on_save is None: + # If required_on_save is not explicitly set, treat it as false unless: + # - it corresponds to a model field with required_on_save=True (such as page title) + # - it corresponds to a non-null, non-text-typed model field (in which case a blank value + # is not valid at the database level) + try: + db_field = self.db_field + except FieldDoesNotExist: + required_on_save = False + else: + required_on_save = getattr(db_field, "required_on_save", False) + + if not required_on_save: opts["defer_required_on_fields"] = [self.field_name] if self.widget: diff --git a/wagtail/admin/panels/title_field_panel.py b/wagtail/admin/panels/title_field_panel.py index 9ba56f0772..a906cadd27 100644 --- a/wagtail/admin/panels/title_field_panel.py +++ b/wagtail/admin/panels/title_field_panel.py @@ -32,7 +32,6 @@ class TitleFieldPanel(FieldPanel): **kwargs, ): kwargs["classname"] = classname - kwargs.setdefault("required_on_save", True) self.apply_if_live = apply_if_live self.placeholder = placeholder self.targets = targets diff --git a/wagtail/models/pages.py b/wagtail/models/pages.py index 62d0801c17..0b6ac72d08 100644 --- a/wagtail/models/pages.py +++ b/wagtail/models/pages.py @@ -283,6 +283,7 @@ class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase): max_length=255, help_text=_("The page title as you'd like it to be seen by the public"), ) + title.required_on_save = True # to reflect title of a current draft in the admin UI draft_title = models.CharField(max_length=255, editable=False) slug = models.SlugField(