0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-12-01 03:31:04 +01:00

Refactor out a BoundInlinePanel class

This commit is contained in:
Matt Westcott 2022-03-15 00:32:30 +00:00 committed by Matt Westcott
parent 490e4299a7
commit 2fd7fe5ae6

View File

@ -360,6 +360,9 @@ class BoundPanel:
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()
@ -888,6 +891,91 @@ class PageChooserPanel(FieldPanel):
return opts
class BoundInlinePanel(BoundPanel):
def __init__(self, panel, instance, request, form):
super().__init__(panel, instance, request, form)
self.label = self.panel.label
if self.form is None:
return
self.formset = self.form.formsets[self.panel.relation_name]
self.child_edit_handler = self.panel.child_edit_handler
self.children = []
for subform in self.formset.forms:
# override the DELETE field to have a hidden input
subform.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()
# ditto for the ORDER field, if present
if self.formset.can_order:
subform.fields[ORDERING_FIELD_NAME].widget = forms.HiddenInput()
self.children.append(
self.child_edit_handler.bind_to(
instance=subform.instance, request=self.request, form=subform
)
)
# if this formset is valid, it may have been re-ordered; respect that
# in case the parent form errored and we need to re-render
if self.formset.can_order and self.formset.is_valid():
self.children.sort(
key=lambda child: child.form.cleaned_data[ORDERING_FIELD_NAME] or 1
)
empty_form = self.formset.empty_form
empty_form.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()
if self.formset.can_order:
empty_form.fields[ORDERING_FIELD_NAME].widget = forms.HiddenInput()
self.empty_child = self.child_edit_handler.bind_to(
instance=empty_form.instance, request=self.request, form=empty_form
)
def html_declarations(self):
return self.empty_child.html_declarations()
def get_comparison(self):
field_comparisons = []
for panel in self.panel.child_edit_handler.children:
field_comparisons.extend(
panel.bind_to(
instance=None, request=self.request, form=None
).get_comparison()
)
return [
functools.partial(
compare.ChildRelationComparison, self.panel.db_field, field_comparisons
)
]
def render(self):
formset = render_to_string(
self.panel.template,
{
"self": self,
"can_order": self.formset.can_order,
},
)
js = self.render_js_init()
return widget_with_script(formset, js)
def render_js_init(self):
return mark_safe(
render_to_string(
self.panel.js_template,
{
"self": self,
"can_order": self.formset.can_order,
},
)
)
class InlinePanel(Panel):
def __init__(
self,
@ -919,7 +1007,8 @@ class InlinePanel(Panel):
)
return kwargs
def get_panel_definitions(self):
@cached_property
def panel_definitions(self):
# Look for a panels definition in the InlinePanel declaration
if self.panels is not None:
return self.panels
@ -928,14 +1017,14 @@ class InlinePanel(Panel):
self.db_field.related_model, exclude=[self.db_field.field.name]
)
def get_child_edit_handler(self):
panels = self.get_panel_definitions()
@cached_property
def child_edit_handler(self):
panels = self.panel_definitions
child_edit_handler = MultiFieldPanel(panels, heading=self.heading)
return child_edit_handler.bind_to_model(self.db_field.related_model)
def get_form_options(self):
child_edit_handler = self.get_child_edit_handler()
child_form_opts = child_edit_handler.get_form_options()
child_form_opts = self.child_edit_handler.get_form_options()
return {
"formsets": {
self.relation_name: {
@ -950,92 +1039,18 @@ class InlinePanel(Panel):
}
}
def html_declarations(self):
return self.get_child_edit_handler().html_declarations()
def get_comparison(self):
field_comparisons = []
for panel in self.get_panel_definitions():
field_comparisons.extend(
panel.bind_to_model(self.db_field.related_model).get_comparison()
)
return [
functools.partial(
compare.ChildRelationComparison, self.db_field, field_comparisons
)
]
def on_model_bound(self):
manager = getattr(self.model, self.relation_name)
self.db_field = manager.rel
def on_form_bound(self):
if self.form is None:
return
self.formset = self.form.formsets[self.relation_name]
self.children = []
for subform in self.formset.forms:
# override the DELETE field to have a hidden input
subform.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()
# ditto for the ORDER field, if present
if self.formset.can_order:
subform.fields[ORDERING_FIELD_NAME].widget = forms.HiddenInput()
child_edit_handler = self.get_child_edit_handler()
self.children.append(
child_edit_handler.bind_to(
instance=subform.instance, request=self.request, form=subform
)
)
# if this formset is valid, it may have been re-ordered; respect that
# in case the parent form errored and we need to re-render
if self.formset.can_order and self.formset.is_valid():
self.children.sort(
key=lambda child: child.form.cleaned_data[ORDERING_FIELD_NAME] or 1
)
empty_form = self.formset.empty_form
empty_form.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()
if self.formset.can_order:
empty_form.fields[ORDERING_FIELD_NAME].widget = forms.HiddenInput()
self.empty_child = self.get_child_edit_handler()
self.empty_child = self.empty_child.bind_to(
instance=empty_form.instance, request=self.request, form=empty_form
def get_bound_panel(self, instance=None, request=None, form=None):
return BoundInlinePanel(
panel=self, instance=instance, request=request, form=form
)
template = "wagtailadmin/panels/inline_panel.html"
def render(self):
formset = render_to_string(
self.template,
{
"self": self,
"can_order": self.formset.can_order,
},
)
js = self.render_js_init()
return widget_with_script(formset, js)
js_template = "wagtailadmin/panels/inline_panel.js"
def render_js_init(self):
return mark_safe(
render_to_string(
self.js_template,
{
"self": self,
"can_order": self.formset.can_order,
},
)
)
# This allows users to include the publishing panel in their own per-model override
# without having to write these fields out by hand, potentially losing 'classname'