blog

Migrating Wagtail ModelAdmin to the new snippet admin views

Rob Moorman

25 november 2022

With the new snippet admin views the usage of modeladmin becomes outdated. The snippets now leverage the preview & history abilities from Wagtail, similar to the workflow of pages:

  • Preview
  • Draft & publish workflow
  • Search
  • Filters

However we find that it's most important to lift upon the core features of the Wagtail CMS so we can translate these snippets as well in the future.

Let's see how we can migrate from our existing modeladmin setup and how it looks.

First of all we have the current modeladmin configuration for a common used Person model:

class Person(models.Model):
    first_name = models.CharField(_("First name"), max_length=255)
    last_name = models.CharField(_("Last name"), max_length=255)
    function = models.CharField(_("Function"), max_length=255)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
        verbose_name=_("image"),
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("first_name"),
                FieldPanel("last_name"),
                FieldPanel("function"),
                FieldPanel("image"),
            ],
            heading=_("person"),
        ),
    ]

    class Meta:
        ordering = ["first_name"]
        verbose_name = _("person")
        verbose_name_plural = _("persons")

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)


class PersonModelAdmin(ModelAdmin):
    model = Person
    list_display = ("first_name", "last_name", "function")
    search_fields = ("first_name", "last_name", "function")

In order to provide our existing model with the latest snippet features we have to extend this model quite a bit:

class Person(
    index.Indexed, PreviewableMixin, DraftStateMixin, RevisionMixin, models.Model
):
    first_name = models.CharField(_("First name"), max_length=255)
    last_name = models.CharField(_("Last name"), max_length=255)
    function = models.CharField(_("Function"), max_length=255)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+",
        verbose_name=_("image"),
    )

    _revisions = GenericRelation("wagtailcore.Revision", related_query_name="person")

    search_fields = [
        index.SearchField("first_name", partial_match=True, boost=10),
        index.SearchField("last_name", partial_match=True, boost=10),
        index.SearchField("function", partial_match=True),
    ]

    panels = [
        MultiFieldPanel(
            [
                FieldPanel("first_name"),
                FieldPanel("last_name"),
                FieldPanel("function"),
                FieldPanel("image"),
            ],
            heading=_("person"),
        ),
        PublishingPanel(),
    ]

    class Meta:
        ordering = ["first_name"]
        verbose_name = _("person")
        verbose_name_plural = _("persons")

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)

    def get_preview_template(self, request, mode_name):
        return "cms/previews/person.html"

With the new SnippetViewSet we create our configuration for our Person model (for now we leave the option to add filters for as it is).

from wagtail.snippets.views.snippets import SnippetViewSet


class PersonViewSet(SnippetViewSet):
    list_display = ["first_name", "last_name"]
Snippet
Snippet

Finally register the snippet with this PersonViewSet (make sure this is done in wagtail_hooks.py as you'll get errors about models which are not loaded yet):

register_snippet(Person, viewset=PersonViewSet)

Meer updates

Dit is wat we recent hebben gedaan.

Beautiful asserts with your Django Test Client

blog

Beautiful asserts with your Django Test Client

Martijn Jacobs

27 maart 2023

Add Plausible to your Terraform CloudFront distribution

blog

Add Plausible to your Terraform CloudFront distribution

Rob Moorman

2 december 2022

Querying json data with Django

hint

Querying json data with Django

Rob Moorman

25 november 2022