Customising the editing interface¶
Customising the tabbed interface¶
As standard, Wagtail organises panels for pages into three tabs: ‘Content’, ‘Promote’ and ‘Settings’. For snippets Wagtail puts all panels into one page. Depending on the requirements of your site, you may wish to customise this for specific page types or snippets - for example, adding an additional tab for sidebar content. This can be done by specifying an
edit_handler attribute on the page or snippet model. For example:
from wagtail.wagtailadmin.edit_handlers import TabbedInterface, ObjectList class BlogPage(Page): # field definitions omitted content_panels = [ FieldPanel('title', classname="full title"), FieldPanel('date'), FieldPanel('body', classname="full"), ] sidebar_content_panels = [ SnippetChooserPanel('advert'), InlinePanel('related_links', label="Related links"), ] edit_handler = TabbedInterface([ ObjectList(content_panels, heading='Content'), ObjectList(sidebar_content_panels, heading='Sidebar content'), ObjectList(Page.promote_panels, heading='Promote'), ObjectList(Page.settings_panels, heading='Settings', classname="settings"), ])
Rich Text (HTML)¶
Wagtail provides a general-purpose WYSIWYG editor for creating rich text content (HTML) and embedding media such as images, video, and documents. To include this in your models, use the
RichTextField function when defining a model field:
from wagtail.wagtailcore.fields import RichTextField from wagtail.wagtailadmin.edit_handlers import FieldPanel class BookPage(Page): book_text = RichTextField() content_panels = Page.content_panels + [ FieldPanel('body', classname="full"), ]
RichTextField inherits from Django’s basic
TextField field, so you can pass any field parameters into
RichTextField as if using a normal Django field. This field does not need a special panel and can be defined with
However, template output from
RichTextField is special and need to be filtered to preserve embedded content. See Rich text (filter).
If you’re interested in extending the capabilities of the Wagtail WYSIWYG editor (
hallo.js), See Extending the WYSIWYG Editor (hallo.js).
Extending the WYSIWYG Editor (
hallo.js plugin names are prefixed with the
"IKS." namespace, but the
name you pass into
registerHalloPlugin() should be without the prefix.
opts is an object passed into the plugin.
For information on developing custom
hallo.js plugins, see the project’s page: https://github.com/bergie/hallo
Image Formats in the Rich Text Editor¶
On loading, Wagtail will search for any app with the file
image_formats.py and execute the contents. This provides a way to customise the formatting options shown to the editor when inserting images in the
As an example, add a “thumbnail” format:
# image_formats.py from wagtail.wagtailimages.formats import Format, register_image_format register_image_format(Format('thumbnail', 'Thumbnail', 'richtext-image thumbnail', 'max-120x120'))
To begin, import the
register_image_format function, and optionally
unregister_image_format function. To register a new
Format, call the
register_image_format with the
Format object as the argument. The
Format class takes the following constructor arguments:
- The unique key used to identify the format. To unregister this format, call
unregister_image_formatwith this string as the only argument.
- The label used in the chooser form when inserting the image into the
The string to assign to the
classattribute of the generated
Any class names you provide must have CSS rules matching them written separately, as part of the front end CSS code. Specifying a
leftwill only ensure that class is output in the generated markup, it won’t cause the image to align itself left.
- The string specification to create the image rendition. For more, see the Using images in templates.
To unregister, call
unregister_image_format with the string of the
name of the
Format as the only argument.
Customising generated forms¶
Wagtail automatically generates forms using the panels configured on the model.
By default, this form subclasses
WagtailAdminPageForm for pages.
A custom base form class can be configured by setting the
base_form_class attribute on any model.
Custom forms for snippets must subclass
and custom forms for pages must subclass
This can be used to add non-model fields to the form, to automatically generate field content, or to add custom validation logic for your models:
from django import forms from wagtail.wagtailadmin.edit_handlers import FieldPanel from wagtail.wagtailadmin.forms import WagtailAdminPageForm from wagtail.wagtailcore.models import Page class EventPageForm(WagtailAdminPageForm): address = forms.CharField() def clean(self): cleaned_data = super(EventPageForm, self).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(EventPageForm, self).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.get_coordinates(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() content_panels = [ FieldPanel('given_name'), FieldPanel('family_name'), FieldPanel('bio'), ] base_form_class = EventPageForm
Wagtail will generate a new subclass of this form for the model,
adding any fields defined in
Any fields already defined on the model will not be overridden by these automatically added fields,
so the form field for a model field can be overridden by adding it to the custom form.