wagtail-nest / wagtail-modeladmin

Add any model in your project to the Wagtail admin. Formerly wagtail.contrib.modeladmin.
Other
22 stars 8 forks source link

Can't easily register ModelAdmin to custom menu (connected to custom hook) #18

Open Quadric opened 5 years ago

Quadric commented 5 years ago

Issue Summary

I have created a custom "submenu", just like current "settings_menu" which appears in "main menu". Let's call it "Sales". I've done that because i need some menu container for additional installable "django-wagtail" apps which will automatically register in this "submenu". Currently i can only register ModelAdmin to "main menu" or using "add_to_settings_menu" property add it to "settings menu"

Steps to Reproduce

I have an ExampleModelAdmin

this is how to register to main menu:

class ExampleModelAdmin(options.ModelAdmin):
    model = models.ExampleModel

options.modeladmin_register(ExampleModelAdmin)

this is how to register to settings menu

class ExampleModelAdmin(options.ModelAdmin):
    model = models.ExampleModel
    add_to_settings_menu = True

options.modeladmin_register(ExampleModelAdmin)

but there is no possibility to easily register using different menu construction hook because in WagtailRegisterable source code there is something like:

wagtail/contrib/modeladmin/options.py

def register_with_wagtail(self):

        @hooks.register('register_permissions')
        def register_permissions():
            return self.get_permissions_for_registration()

        @hooks.register('register_admin_urls')
        def register_admin_urls():
            return self.get_admin_urls_for_registration()

        menu_hook = (
            'register_settings_menu_item' if self.add_to_settings_menu else
            'register_admin_menu_item'
        )

        @hooks.register(menu_hook)
        def register_admin_menu_item():
            return self.get_menu_item()

It would solve the problem if menu_hook can be accessed as a ModelAdmin property. For now it's hardcoded just for these values:

        menu_hook = (
            'register_settings_menu_item' if self.add_to_settings_menu else
            'register_admin_menu_item'
        )

So the whole "WagtailRegisterable" could look like this:

class WagtailRegisterable:
    """
    Base class, providing a more convenient way for ModelAdmin or
    ModelAdminGroup instances to be registered with Wagtail's admin area.
    """
    add_to_settings_menu = False
    exclude_from_explorer = False
    menu_hook = None

    def register_with_wagtail(self):

        @hooks.register('register_permissions')
        def register_permissions():
            return self.get_permissions_for_registration()

        @hooks.register('register_admin_urls')
        def register_admin_urls():
            return self.get_admin_urls_for_registration()

        if menu_hook is None:
            menu_hook = (
                'register_settings_menu_item' if self.add_to_settings_menu else
                'register_admin_menu_item'
            )

        @hooks.register(menu_hook)
        def register_admin_menu_item():
            return self.get_menu_item()

        # Overriding the explorer page queryset is a somewhat 'niche' / experimental
        # operation, so only attach that hook if we specifically opt into it
        # by returning True from will_modify_explorer_page_queryset
        if self.will_modify_explorer_page_queryset():
            @hooks.register('construct_explorer_page_queryset')
            def construct_explorer_page_queryset(parent_page, queryset, request):
                return self.modify_explorer_page_queryset(
                    parent_page, queryset, request)

    def will_modify_explorer_page_queryset(self):
        return False

and the registration:

class ExampleModelAdmin(options.ModelAdmin):
    model = models.ExampleModel
    menu_hook = 'construct_sales_menu_item'

options.modeladmin_register(ExampleModelAdmin)

alternatively:

class WagtailRegisterable:
    """
    Base class, providing a more convenient way for ModelAdmin or
    ModelAdminGroup instances to be registered with Wagtail's admin area.
    """
    add_to_settings_menu = False
    exclude_from_explorer = False

    def register_with_wagtail(self, menu_hook=None):

        @hooks.register('register_permissions')
        def register_permissions():
            return self.get_permissions_for_registration()

        @hooks.register('register_admin_urls')
        def register_admin_urls():
            return self.get_admin_urls_for_registration()

        if menu_hook is None:
            menu_hook = (
                'register_settings_menu_item' if self.add_to_settings_menu else
                'register_admin_menu_item'
            )

        @hooks.register(menu_hook)
        def register_admin_menu_item():
            return self.get_menu_item()

        # Overriding the explorer page queryset is a somewhat 'niche' / experimental
        # operation, so only attach that hook if we specifically opt into it
        # by returning True from will_modify_explorer_page_queryset
        if self.will_modify_explorer_page_queryset():
            @hooks.register('construct_explorer_page_queryset')
            def construct_explorer_page_queryset(parent_page, queryset, request):
                return self.modify_explorer_page_queryset(
                    parent_page, queryset, request)

    def will_modify_explorer_page_queryset(self):
        return False

and registration:

class ExampleModelAdmin(options.ModelAdmin):
    model = models.ExampleModel

options.modeladmin_register(ExampleModelAdmin, 'construct_sales_menu_item')

Technical details