How to Hide And Auto-populate Title Field of a Page in Wagtail CMS
Feb 20, 2018 · Updated: Jul 17, 2021 · by Tim Kamanin
Given
from django.db import models
from wagtail.wagtailsnippets.models import register_snippet
class CountryPage(Page):
country = models.ForeignKey(
"wagtail_simple_countries.Country",
blank=False,
null=True,
on_delete=models.SET_NULL,
)
class Country(models.Model):
name = models.CharField(max_length=128)
Task
I want to have the title field of my CountryPage to be auto-populated with a name of the related country model.
Solution
-
Add
content_panelstoCountryPagewithout merging them withcontent_panelsof the parentPageclass.class CountryPage(Page): country = models.ForeignKey( "wagtail_simple_countries.Country", blank=False, null=True, on_delete=models.SET_NULL, ) content_panels = [ FieldPanel("country"), ]We do this to exclude title field from the edit page form.
-
Override save method of the
CountryPagemodel to set title from the relatedCountryname.class CountryPage(Page): country = models.ForeignKey( "wagtail_simple_countries.Country", blank=False, null=True, on_delete=models.SET_NULL, ) content_panels = [ FieldPanel("country"), ] def save(self, *args, **kwargs): self.title = self.country.name super().save(*args, **kwargs) -
Add a Javascript code that auto-populates slug field with a value of the chosen country:
function initSlugAutoPopulateFromCountry() { var slugFollowsTitle = false; $("#id_country").on("focus", function () { /* slug should only follow the title field if its value matched the title's value at the time of focus */ var currentSlug = $("#id_slug").val(); // If select value is not empty we get current selection's label. var value = this.value !== "" ? this.options[this.selectedIndex].innerHTML : ""; var slugifiedTitle = cleanForSlug(value, true); slugFollowsTitle = currentSlug == slugifiedTitle; }); $("#id_country").on("change", function () { if (slugFollowsTitle) { var label = this.options[this.selectedIndex].innerHTML; var slugifiedTitle = cleanForSlug(label, true); $("#id_slug").val(slugifiedTitle); } }); } $(function () { /* Only non-live pages should auto-populate the slug from the title */ if (!$("body").hasClass("page-is-live")) { initSlugAutoPopulateFromCountry(); } });You can save this files as
static/js/slug_from_country.js -
Load the Javascript code into Wagtail's page editor via hooks. To do that, create a
wagtail_hooks.pyfile in your Django app with the following content:from django.utils.html import format_html_join from django.conf import settings from wagtail.wagtailcore import hooks @hooks.register("insert_editor_js") def editor_js(): js_files = [ "countries/js/slug_from_country.js", ] js_includes = format_html_join( "\n", '<script src="{0}{1}"></script>', ((settings.STATIC_URL, filename) for filename in js_files), ) return js_includes
That's all; you should now see a Country Page edit form without the title field but with the country name selector that dynamically populates the slug field. After you save the page, its title should also be set to the related country name.
Hey, if you've found this useful, please share the post to help other folks find it: