In Wagtail document, I find an explanatory example showing how you can customize the behavior of admin form adding a few validation and save perks:
from django import forms
import geocoder # not in Wagtail, for example only - http://geocoder.readthedocs.io/
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.admin.forms import WagtailAdminPageForm
from wagtail.core.models import Page
class EventPageForm(WagtailAdminPageForm):
address = forms.CharField()
def clean(self):
cleaned_data = super().clean()
# Make sure that the event starts before it ends
start_date = cleaned_data['start_date']
end_date = cleaned_data['end_date']
if start_date and end_date and start_date > end_date:
self.add_error('end_date', 'The end date must be after the start date')
return cleaned_data
def save(self, commit=True):
page = super().save(commit=False)
# Update the duration field from the submitted dates
page.duration = (page.end_date - page.start_date).days
# Fetch the location by geocoding the address
page.location = geocoder.arcgis(self.cleaned_data['address'])
if commit:
page.save()
return page
class EventPage(Page):
start_date = models.DateField()
end_date = models.DateField()
duration = models.IntegerField()
location = models.CharField(max_length=255)
content_panels = [
FieldPanel('title'),
FieldPanel('start_date'),
FieldPanel('end_date'),
FieldPanel('address'),
]
base_form_class = EventPageForm
All and all it shows how you can ensure date fields are set correct before saving the form and so on. Great, my question then will be if the form contains a parentalkey field ?? like this:
class EventPage(Page):
start_date = models.DateField()
end_date = models.DateField()
duration = models.IntegerField()
location = models.CharField(max_length=255)
content_panels = [
FieldPanel('title'),
FieldPanel('start_date'),
FieldPanel('end_date'),
FieldPanel('address'),
InlinePanel('image_relations')
]
base_form_class = EventPageForm
class EventPageImageRelations(Orderable):
parent = ParentalKey(
EventPage,
related_name="image_relations",
on_delete=models.CASCADE
)
image = models.ForeignKey(
'wagtailimages.Image',
on_delete=models.CASCADE,
related_name='+'
)
date = models.DateField()
panels = [
ImageChooserPanel('image'),
FieldPanel('date')
]
Now, imagine that you'd like to run a check before saving to ensure that the designated date for each image is enter after the start_date. I find this challenging how can get the value on a form for a foreign key relation!