Wagtail has the modeladmin module in contrib which allows you to edit any Django model through the Wagtail admin interface. Unfortunately it's not very flexible, the code calls the get_edit_handler method on the admin class and the panels property of the model can only be a list.
In one project I have a base model that many other models are derived from and wanted to build the panels dynamically. The code below shows how I did it.
I chose to break the Wagtail convention and defined the admin fields on the admin class, but I get the additional fields from the model itself. It's somewhat messy, but it's my mess.
from wagtail.admin.edit_handlers import FieldPanel from wagtail.admin.edit_handlers import MultiFieldPanel from wagtail.admin.edit_handlers import ObjectList from wagtail.contrib.modeladmin.options import ModelAdmin class DynamicPanelMixin: def get_edit_handler(self, instance, request): return ObjectList(self._get_panels(instance)) def _get_panels(self, instance): return [ *self._get_head_panels(instance), MultiFieldPanel( self._get_multi_panels(instance), heading="Collapsed", classname="collapsible collapsed", ), ] def _get_head_panels(self, instance): panels = [ FieldPanel("foo"), ] return panels + getattr(instance, "head_panels", ) def _get_multi_panels(self, instance): panels = [ FieldPanel("bar"), ] return panels + getattr(instance, "multi_panels", ) # class MyModelAdmin(DynamicPanelMixin, ModelAdmin): # pass