From 6e6ef3376c490487078918370d2c0fc83117da88 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Tue, 15 Mar 2022 02:12:25 +0000 Subject: [PATCH] Remove bound-EditHandler methods from base EditHandler class --- wagtail/admin/panels.py | 277 ++++++++-------------- wagtail/admin/tests/test_edit_handlers.py | 18 +- wagtail/contrib/forms/panels.py | 6 +- 3 files changed, 108 insertions(+), 193 deletions(-) diff --git a/wagtail/admin/panels.py b/wagtail/admin/panels.py index ac4e229afb..7fe2ae9592 100644 --- a/wagtail/admin/panels.py +++ b/wagtail/admin/panels.py @@ -104,6 +104,81 @@ def extract_panel_definitions_from_model_class(model, exclude=None): UNSET = object() +class BoundPanel: + def __init__(self, panel, instance, request, form): + self.panel = panel + self.instance = instance + self.request = request + self.form = form + + self.heading = self.panel.heading + self.help_text = self.panel.help_text + + @property + def classname(self): + return self.panel.classname + + def classes(self): + return self.panel.classes() + + def field_type(self): + return self.panel.field_type() + + def id_for_label(self): + return self.panel.id_for_label() + + def is_shown(self): + return True + + def render_as_object(self): + return self.render() + + def render_as_field(self): + return self.render() + + def render(self): + return mark_safe(render_to_string(self.panel.template, {"self": self})) + + def html_declarations(self): + return "" + + def get_comparison(self): + return [] + + def render_missing_fields(self): + """ + Helper function: render all of the fields that are defined on the form but not "claimed" by + any panels via required_fields. These fields are most likely to be hidden fields introduced + by the forms framework itself, such as ORDER / DELETE fields on formset members. + (If they aren't actually hidden fields, then they will appear as ugly unstyled / label-less fields + outside of the panel furniture. But there's not much we can do about that.) + """ + rendered_fields = self.panel.get_form_options().get("fields", []) + missing_fields_html = [ + str(self.form[field_name]) + for field_name in self.form.fields + if field_name not in rendered_fields + ] + + return mark_safe("".join(missing_fields_html)) + + def render_form_content(self): + """ + Render this as an 'object', ensuring that all fields necessary for a valid form + submission are included + """ + return mark_safe(self.render_as_object() + self.render_missing_fields()) + + def __repr__(self): + return "<%s with model=%s instance=%s request=%s form=%s>" % ( + self.__class__.__name__, + self.panel.model, + self.instance, + self.request, + self.form.__class__.__name__, + ) + + class Panel: """ Defines part (or all) of the edit form interface for pages and other models within the Wagtail @@ -113,14 +188,13 @@ class Panel: as HTML. """ + bound_panel_class = BoundPanel + def __init__(self, heading="", classname="", help_text=""): self.heading = heading self.classname = classname self.help_text = help_text self.model = None - self.instance = None - self.request = None - self.form = None def clone(self): return self.__class__(**self.clone_kwargs()) @@ -188,15 +262,6 @@ class Panel: required_formsets.is_original_method = True - # return any HTML that needs to be output on the edit page once per edit handler definition. - # Typically this will be used to define snippets of HTML within blocks - # for JavaScript code to work with. - def html_declarations(self): - return "" - - def is_shown(self): - return True - def bind_to_model(self, model): new = self.clone() new.model = model @@ -224,39 +289,17 @@ class Panel: return self.get_bound_panel(instance=instance, request=request, form=form) def get_bound_panel(self, instance=None, request=None, form=None): - new = self.clone() - new.model = self.model - new.on_model_bound() # necessary because the cloned edit handler no longer has any state set up - # from when we called on_model_bound in bind_to_model - new.instance = instance - new.request = request - new.form = form - - new.on_instance_bound() - new.on_request_bound() - new.on_form_bound() - - return new + return self.bound_panel_class( + panel=self, instance=instance, request=request, form=form + ) def on_model_bound(self): pass - def on_instance_bound(self): - pass - - def on_request_bound(self): - pass - - def on_form_bound(self): - pass - def __repr__(self): - return "<%s with model=%s instance=%s request=%s form=%s>" % ( + return "<%s with model=%s>" % ( self.__class__.__name__, self.model, - self.instance, - self.request, - self.form.__class__.__name__, ) def classes(self): @@ -283,49 +326,6 @@ class Panel: """ return "" - def render_as_object(self): - """ - Render this object as it should appear within an ObjectList. Should not - include the

heading or help text - ObjectList will supply those - """ - # by default, assume that the subclass provides a catch-all render() method - return self.render() - - def render_as_field(self): - """ - Render this object as it should appear within a