Example:
Imagine you have a model like "Organisation" consisting of attributes like name, employees and so on and you want to create multiple views for it (through the admin panel), e.g. a "list of employees", "organisation overview".
Now, since you are using ModelAdmin, you would like to have a "employee list" and "overview" button beneath each organisation object in the index view, so you can easily access both object-views.
Note: You could use inspect_view for one action, but not for multiple actions.
Currently it is quite tricky implement new action-buttons with separate views because:
Adding further buttons is not described directly, the documentation only hints at ButtonHelper
Registering new model action-urls is undocumented
Far too many steps needed:
Create a super class of ButtonHelper
Add your button generating function to button ButtonHelper (like delete_button())
Overload ButtonHelper.get_buttons_for_obj() and append your button to the existing ones
Create a custom view function in your ModelAdmin class (like delete_view())
Overload ModelAdmin.get_admin_urls_for_registration() and append your custom view with the action url
specify button_helper_class=.. in your ModelAdmin
This problem is also discussed in wagtail/wagtail-modeladmin#7 and wagtail/wagtail-modeladmin#10
Describe the solution you'd like
In contrast to wagtail/wagtail-modeladmin#7 and wagtail/wagtail-modeladmin#10, I am proposing a very minimal change in ButtonHelper and ModelAdmin only.
The goal is to simplify the steps above without breaking any backwards compatibility in Wagtail, so the feature is lightweight but effective:
By removing the need to overload the two method above, a lot of code is saved and the complexity is reduced by a lot
The button generating functions (add_button(), edit_button(), ..) are all almost the same and can be defaulted for custom buttons
Simple custom buttons should be definable in ButtonHelper with a simple data structure (e.g. a list containing the action, label, title, ..)
The views (with their actions) should be definable in ModelAdmin using a simpler structure as well
A scratch code can be seen below.
Describe alternatives you've considered
One alternative would be to rewrite ButtonHelper as mentioned in wagtail/wagtail-modeladmin#10.
By changing ButtonHelper heavily, old Wagtail-Projects might be broken, so this is rather a long term goal.
Additional context
Changes to Wagtail:
# Changes to ButtonHelper
class ButtonHelper:
# Default button generator for custom/extra buttons (structured like add_button)
def extra_button(self, url=None, label='', title=None, classnames_add=None, classnames_exclude=None):
if classnames_add is None:
classnames_add = []
if classnames_exclude is None:
classnames_exclude = []
cn = self.finalise_classname(classnames_add, classnames_exclude)
if not title:
title = label
return {
'url': url,
'label': label,
'classname': cn,
'title': title,
}
def get_buttons_for_obj(self, obj, exclude=None, classnames_add=None,
classnames_exclude=None):
# OLD CODE HERE
# New code
# Check if the custom data structure is present
if hasattr(self, "custom_object_buttons"):
button_list = self.custom_object_buttons
for action, kw in button_list:
# TODO unite kw['classnames_add'] and classnames_add
# TODO unite kw['classnames_exclude'] and classnames_exclude
# create and append the button using the regular url pattern
button = self.extra_button(self.url_helper.get_action_url(action, pk), **kw)
btns.append(button)
return btns
class ModelAdmin:
def get_admin_urls_for_registration(self):
# OLD CODE HERE
# New code
# create url pattern for each custom view, just like for "add", "edit", ...
urls = urls + tuple(
re_path(
self.url_helper.get_action_url_pattern(action),
view,
name=self.url_helper.get_action_url_name(action))
for action, view in self.get_custom_object_views()
)
return urls
# fallback method
def get_custom_object_views(self):
return []
Adding Buttons would now be much easier:
class MyButtonHelper(ButtonHelper):
# custom definitions
# (action, attributes)
custom_object_buttons = [
("empolyees", {"label": 'Employee List', "add_class":["some_class"]}),
("overview", {"label": 'Overview', "title": 'Show a detailed overview table'}),
..
]
class MyModelWagtailAdmin(ModelAdmin):
button_helper_class = MyButtonHelper
def empolyees_view(self, request, instance_pk):
# some call to View.as_view(..)
def overview_view(self, request, instance_pk):
# some call to OtherView.as_view(..)
# Define custom object views
# This is a function because self is needed
# It would be even nicer to have only a list of actions
# and to automatically return self.{action}_view
def get_custom_object_views(self):
return [
# (action, view)
("empolyees", self.empolyees_view),
("overview", self.overview_view),
]
If you like this suggestion, I will create a pull request for this feature
Is your proposal related to a problem?
Example: Imagine you have a model like "Organisation" consisting of attributes like name, employees and so on and you want to create multiple views for it (through the admin panel), e.g. a "list of employees", "organisation overview". Now, since you are using
ModelAdmin
, you would like to have a "employee list" and "overview" button beneath each organisation object in the index view, so you can easily access both object-views.Note: You could use
inspect_view
for one action, but not for multiple actions.Currently it is quite tricky implement new action-buttons with separate views because:
ButtonHelper
ButtonHelper
ButtonHelper
(likedelete_button()
)ButtonHelper.get_buttons_for_obj()
and append your button to the existing onesModelAdmin
class (likedelete_view()
)ModelAdmin.get_admin_urls_for_registration()
and append your custom view with the action urlbutton_helper_class=..
in yourModelAdmin
This problem is also discussed in wagtail/wagtail-modeladmin#7 and wagtail/wagtail-modeladmin#10
Describe the solution you'd like
In contrast to wagtail/wagtail-modeladmin#7 and wagtail/wagtail-modeladmin#10, I am proposing a very minimal change in
ButtonHelper
andModelAdmin
only. The goal is to simplify the steps above without breaking any backwards compatibility in Wagtail, so the feature is lightweight but effective:add_button()
,edit_button()
, ..) are all almost the same and can be defaulted for custom buttonsButtonHelper
with a simple data structure (e.g. a list containing the action, label, title, ..)ModelAdmin
using a simpler structure as wellA scratch code can be seen below.
Describe alternatives you've considered
One alternative would be to rewrite
ButtonHelper
as mentioned in wagtail/wagtail-modeladmin#10. By changingButtonHelper
heavily, old Wagtail-Projects might be broken, so this is rather a long term goal.Additional context
Changes to Wagtail:
Adding Buttons would now be much easier:
If you like this suggestion, I will create a pull request for this feature