question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use base_form_class in InlinePanel.

See original GitHub issue

Currently, there is no possible way to specify a form for an inline. For consistency, it should be possible to specify base_form_class in any Model, just like we can do it with Page.

In my case, this is blocking since I would like to use a form field that is not a database field, then parse its data and dispatch it into multiple database fields.

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:15
  • Comments:11 (2 by maintainers)

github_iconTop GitHub Comments

5reactions
regmegcommented, Jul 22, 2019

I’ve dug into the wagtail source code and I think I found the way of how to access the form controls for the orderable (this might work for other types of inline elements/haven’t tested those).

Let’s say you have a model for a page,

class TestPage(Page):

    testPageTitle = RichTextField(blank=True, max_length=250)

    content_panels = Page.content_panels + [
	FieldPanel('testPageTitle'),
	InlinePanel('test_page_field')
    ]

    base_form_class = TestPageForm

with some orderable model, that is linked to the page through a related name ‘test_page_field’,

class TestPageField(Orderable):
    page = ParentalKey(TestPage, on_delete=models.CASCADE, related_name='test_page_field')

    testPageFieldTitle = models.CharField(blank=True, max_length=250)

    panels = [
	FieldPanel('testPageFieldFieldTitle')
    ]

then you can access that within the clean method of the page, via self.formsets['test_page_field'].forms, which is a list of Django form objects, where the regular checks can be done and .add_error() method can be used. The relevant base_form_class would look as follows:

class TestPageForm(WagtailAdminPageForm):

    def clean(self):
	cleaned_data = super().clean()

	#loop over linked orderables
	for form in self.formsets['test_page_field'].forms:

	    #check first if form is valid, otherwise cleaned_data will not be accesible/set
	    if form.is_valid():
	        cleaned_form_data = form.clean()
	        testPageFieldFieldTitle = cleaned_form_data.get('testPageFieldFieldTitle')

	        #execute some validation condition, and raise the error if it fails
	        if testPageFieldFieldTitle is None:
	            form.add_error('testPageFieldFieldTitle', 'please dont leave me empty')

	return cleaned_data

I hope this helps.

0reactions
engAmirEngcommented, Sep 2, 2022

I think I find the solution:

class SomeOrderable(Orderable):
    panels = [
        SnippetChooserPanel("some_snippet"),
        FieldPanel("my_field_thst_is_not_in_model"),
    ]
    page = ParentalKey(
        "SomePage",
        related_name="page_someorderable",
        on_delete=models.CASCADE,
    )
    some_snippet= models.ForeignKey(
        "SomModel", on_delete=models.CASCADE
    )
class MyWagtailAdminModelForm(WagtailAdminModelForm):
    my_field_thst_is_not_in_model = forms.IntegerField(widget=forms.Select(choices=((1, "one"), (2, "two"))))

class MyInlinePanel(InlinePanel):
    def __init__(self, relation_name, form=None, *args, **kwargs):
        self.form = form
        super(MyInlinePanel, self).__init__(relation_name, *args, **kwargs)
    def clone_kwargs(self):
        kwargs = super().clone_kwargs()
        kwargs.update(form=self.form)
        return kwargs
    def get_form_options(self):
        form_options = super(MyInlinePanel, self).get_form_options()
        form_options['formsets'][self.relation_name].update(form=self.form)
        return form_options

class SomePage(Page):
    content_panels = Page.content_panels + [
        MyInlinePanel("page_someorderable", form=MyWagtailAdminModelForm),
    ]

1-you define your custom form for the orderable that as you know it should subclass the WagtailAdminModelForm 2-subclass the InlinePanel as it’s shown in the pic I try this works on wagtail 3

A bigger question, is there any particular reason that it is not a part of wagtail support? maybe some issues and bugs?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Customising the editing interface — Wagtail 2.12 documentation
Wagtail automatically generates forms using the panels configured on the model. By default, this form subclasses WagtailAdminModelForm , or WagtailAdminPageForm ...
Read more >
How to use InlinePanel in ModelAdmin? - Stack Overflow
Wagtail relies on the django-modelcluster library to allow the parent and child models to be handled in forms as a single unit.
Read more >
Wagtail Documentation - Read the Docs
To add this to the admin interface, use the InlinePanel edit panel class: content_panels = [ ... A custom base form class can...
Read more >
Wagtail 2.8 documentation
To add this to the admin interface, use the InlinePanel edit panel class: ... A custom base form class can be configured by...
Read more >
Wagtail Tip #1: How to replace ParentalManyToManyField ...
In this Wagtail tip, I will talk about How to replace `ParentalManyToManyField` using Wagtail InlinePanel.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found