wagtailwagtail-adminwagtail-snippet

Wagtail modeladmin-snippets migration


I have a CompanyStatus model that I want to register as a snippet in Wagtail to manage it from the admin panel. This model is used as a ForeignKey field in another model, Company. In the admin panel for Company, I want to be able to select CompanyStatus using a FieldPanel.

After registering CompanyStatus as a snippet, the selection widget in the FieldPanel for Company stops working correctly - it does not load the statuses. I need a way to register CompanyStatus as a snippet while maintaining the functionality of selecting a status in the FieldPanel for the Company model.

CompanyStatus is defined as a standard Django model with several fields, including name and description. Company is a model that has a ForeignKey to CompanyStatus. After registering CompanyStatus as a snippet, the selection functionality in the FieldPanel for Company stops working. How can I register CompanyStatus as a snippet in Wagtail while still retaining the ability to select this status in the FieldPanel for the Company model?


Solution

  • Registering CompanyStatus as a snippet will set up a snippet chooser widget (the kind with a button that opens a modal window with the items to pick from) to be used as the default form widget for ForeignKeys to that model - see Defining admin form widgets in the Wagtail docs. It's unclear why this would cause things to break rather than just swapping out the form widget - perhaps you're overriding the template for the Company edit form and left out the JS includes that the snippet chooser widget relies on? - but in any case, you can revert this behaviour so that it uses a plain select input, like non-snippet models do.

    The quick fix is to specify the widget within the FieldPanel definition:

    from django import forms
    
    class Company(models.Model):
        # ...
        panels = [
            FieldPanel("company_status", widget=forms.Select),
        ]
    

    Alternatively, to fix this 'properly' for all ForeignKeys to CompanyStatus, not just that specific one on Company - you can configure the SnippetViewSet for CompanyStatus so that skips the step of registering the widget. Where you currently have:

    from wagtail.snippets.views.snippets import SnippetViewSet
    
    class CompanyStatusViewSet(SnippetViewSet):
        model = CompanyStatus
    

    change this to:

    from wagtail.snippets.views.snippets import SnippetViewSet
    from wagtail.admin.viewsets.chooser import ChooserViewSet
    
    class CompanyStatusChooserViewSet(ChooserViewSet):
        register_widget = False
    
    class CompanyStatusViewSet(SnippetViewSet):
        model = CompanyStatus
        chooser_viewset_class = CompanyStatusChooserViewSet