I want to automatically generate field content based on another, editor-filled field for a wagtail page model on page save.
I followed the wagtail docs and I am able to populate and save a field programmatically on page save/publish:
from wagtail.models import Page
from wagtail.admin.forms import WagtailAdminPageForm
class TestPageForm(WagtailAdminPageForm):
def clean(self):
cleaned_data = super().clean()
print("-> called TestPageForm.clean()")
return cleaned_data
def save(self, commit=True):
print(f"1 {commit=}")
page = super().save(commit=False)
print(f"2 {commit=}")
print("-> called TestPageForm.save()")
# process something, save result to instance field, e.g.:
# page.pdf_cover_image = get_cover_image(self.cleaned_data["pdf"])
if commit:
print(f"{commit=}: calling page.save()")
page.save()
return page
class TestPage(Page):
base_form_class = TestPageForm
But the forms clean()
and save()
methods are called multiple times, even when I did not expect them to be called at all:
Edit page
Requesting the page instance via wagtail backend ("Edit page"):
http://127.0.0.1:8000/admin/pages/139/edit/
⇒
[10/May/2023 10:35:37] "GET /admin/pages/139/edit/ HTTP/1.1" 200 71082
[...assets...]
-> called TestPageForm.clean()
1 commit=False
2 commit=False
-> called TestPageForm.save()
[10/May/2023 10:35:37] "GET /admin/pages/139/edit/preview/?in_preview_panel=true&mode= HTTP/1.1" 200 0
[10/May/2023 10:35:37] "DELETE /admin/pages/139/edit/preview/ HTTP/1.1" 200 17
-> called TestPageForm.clean()
[10/May/2023 10:35:37] "POST /admin/pages/139/edit/preview/ HTTP/1.1" 200 40
-> called TestPageForm.clean()
1 commit=False
-> called TestPageForm.clean()
2 commit=False
-> called TestPageForm.save()
1 commit=False
2 commit=False
-> called TestPageForm.save()
[10/May/2023 10:35:37] "GET /admin/pages/139/edit/preview/?in_preview_panel=true&mode= HTTP/1.1" 200 0
Save page
[10/May/2023 10:35:37] "GET /admin/pages/139/edit/preview/?in_preview_panel=true&mode= HTTP/1.1" 200 0
-> called TestPageForm.clean()
1 commit=False
2 commit=False
-> called TestPageForm.save()
[10/May/2023 10:38:10] "POST /admin/pages/139/edit/ HTTP/1.1" 302 0
[10/May/2023 10:38:10] "GET /admin/pages/8/ HTTP/1.1" 200 45356
So on page save the forms clean()
and save()
methods are called only once - but as commit
is always False
I'm not able to differentiate between all these clean-and-save-calls...
So how do I trigger a custom save()-action which will only be called once and only on page save()?