Feb 20, 2018 · Updated: Jul 17, 2021 · by Tim Kamanin
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)
I want to have the title field of my CountryPage
to be auto-populated with a name of the related country model.
Add content_panels
to CountryPage
without merging them with content_panels
of the parent Page
class.
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 CountryPage
model to set title from the related Country
name.
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.py
file 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: