Search code examples
djangodrop-down-menuwagtailwagtail-admin

How to prefix a foreign key object to a model field in Wagtail admin?


enter image description here

In this case, each feature has one Epic (models.Model)

epic = models.ForeignKey(Epic, on_delete=models.CASCADE, default='')

In the admin drop-down (and only there) I would like to show each item as:

epic.name - feature.name

Because some of my features have a similar name but different epics. I can't change the __ str __ function of the Feature model or it will affect the whole app.

How can I achieve that?


Solution

  • One way to do this is to subclass Django's ModelChoiceField, and override the label_from_instance method that provides the label:

    from django.forms import ModelChoiceField
    
    class FeatureChoiceField(ModelChoiceField):
        def label_from_instance(self, obj):
            return "%s - %s" % (obj.epic.name, obj.name)
    

    You'll then need to customise the edit form to use that custom form field type in place of the default ModelChoiceField:

    from wagtail.admin.forms import WagtailAdminModelForm
    # note - use WagtailAdminPageForm if this is a page model rather than a
    # plain Django model managed through snippets / ModelAdmin
    
    class ScopeForm(WagtailAdminModelForm):
        feature = FeatureChoiceField(queryset=Feature.objects.all())
    
    
    class Scope(models.Model):
        # ...
    
        base_form_class = ScopeForm