Ответ
ModelAdmin
не использует ту же систему для построения кнопок, перечисленных в их представлениях.
Вместо этого у него есть понятие «вспомогательные классы», они используются для генерации URL-адресов и проверок разрешений, которые, в свою очередь, используются для генерации кнопок, появляющихся в различных представлениях.
http://docs.wagtail.io/en/v2.5.1/reference/contrib/modeladmin/primer.html#overriding-helper-classes
Вам нужно будет настроить пользовательский button_helper_class для экземпляра ModelAdmin
, который будет генерировать пользовательские кнопки, которые вы хотите использовать в своем IndexView
. Для этого вам нужно будет импортировать и расширять класс PageButtonHelper
с помощью пользовательского метода get_buttons_for_obj
, который будет возвращать список кнопок.
Пример кода
# wagtail_hooks.py
from django.urls import reverse
from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from wagtail.contrib.modeladmin.helpers import (PageAdminURLHelper, PageButtonHelper)
# MyPage model import not included but will be needed
class CustomPageAdminURLHelper(PageAdminURLHelper):
def get_action_url(self, action, *args, **kwargs):
if action == 'add-child':
# note: add_subpage is used as the internal name for adding child pages
url_name = 'wagtailadmin_pages:add_subpage'
target_url = reverse(url_name, args=args, kwargs=kwargs)
return target_url
# for every other case - just call the parent method
return super().get_action_url(action, *args, **kwargs)
class CustomPageButtonHelperClass(PageButtonHelper):
add_child_button_classnames = ['add-child'] # can be anything - just setting this to match convention
# add a new button generator that mimics the 'copy_button' from existing code
def add_child_button(self, pk, classnames_add=[], classnames_exclude=[]):
classnames = self.add_child_button_classnames + classnames_add
final_classnames = self.finalise_classname(classnames, classnames_exclude)
return {
# if we wanted - we can skip the creation of CustomPageAdminURLHelper & generate the URL here
# but this may work against reusability later
'url': self.url_helper.get_action_url('add-child', pk), # may need to wrap pk in quote if it could contain non-url-safe chars
'label': 'Add Child',
'classname': final_classnames,
'title': 'Add Child uner this %s' % self.verbose_name
}
# override the PageButtonHelper method to 'add' custom buttons
def get_buttons_for_obj(self, obj, exclude=[], classnames_add=[], classnames_exclude=[]):
# call the parent class method to get the default set of buttons
buttons = super().get_buttons_for_obj(obj, exclude, classnames_add, classnames_exclude)
# set up some variables to do user checks and also get the primary key (id)
permission_helper = self.permission_helper
user = self.request.user
pk = getattr(obj, self.opts.pk.attname)
# many existing permission helpers are already available - see wagtail/contrib/modeladmin/helpers/permission.py
if ('add-child' not in exclude and permission_helper.user_can_create(user)):
# above we follow the convention set up where buttons can be included/excluded easier
# we also do a permissions check
# finally we build the button and add it to the end of the buttons list
add_child_button = self.add_child_button(pk, classnames_add, classnames_exclude)
buttons.append(add_child_button)
return buttons
class CustomAdmin(ModelAdmin):
model = MyPage
menu_label = 'custom ModelAdmin'
button_helper_class = CustomPageButtonHelperClass # added to enable custom button generation
url_helper_class = CustomPageAdminURLHelper # added to enable custom url generation
list_display = ('title', "live")
list_filter = ("date")
search_fields = ("title")
modeladmin_register(CustomAdmin)
Пояснение кода
CustomPageButtonHelperClass
- Переопределите
get_buttons_for_obj
, добавив кнопку add_child_.
- Используйте существующий класс помощника по разрешениям для выполнения некоторых проверок, это избавит от необходимости переписывать логику user & auth, которая может быть подвержена ошибкам
- Вызвать метод (который мы добавим) для генерации содержимого кнопки,
add_child_button
- Добавить метод
add_child_button
- должен возвращать объект с URL, меткой, именем класса и заголовком. Попытайтесь сохранить существующие соглашения в месте, где имена классов могут быть добавлены / удалены глобально
- Самым сложным является генерирование URL, мы будем использовать существующую структуру помощников URL, но вы можете просто сгенерировать этот URL в строке.
CustomPageAdminURLHelper
- Переопределите метод
get_action_url
и обработайте конкретный случай, о котором мы заботимся, где «действие» равно 'add-child'
- Этот метод должен просто возвращать строку (которая будет относительным URL), лучше всего использовать существующую систему реверсирования URL Django.
- URL-адрес для добавления дочерней страницы:
'wagtailadmin_pages:add_subpage'
- Наконец, вызовите утилиту реверса Django с переданными в args / kwargs, и вы получите красивый URL взамен.
CustomAdmin
- Последний шаг - установка этих пользовательских классов помощников по URL и кнопкам в вашем экземпляре CustomAdmin.
- Для этого просто нужно, чтобы
button_helper_class
и url_helper_class
были установлены на соответствующие переопределения помощников.
Дополнительные замечания и предостережения
- Внимательно прочитайте документы ModelAdmin, они очень хорошо изложены и очень помогают. http://docs.wagtail.io/en/v2.5.1/reference/contrib/modeladmin/index.html
- Некоторые аспекты отсутствуют, но папка helpers в кодовой базе довольно легко читается и должна помочь вам разобраться с потоком кода, который вы настраиваете.
- Предполагается, что вы хотите использовать эти пользовательские помощники только на моделях страниц. Существуют тонкие различия в том, как ModelAdmin обрабатывает страницы и другие объекты, вы можете добавлять дополнительные проверки, но это зависит от вас.
- Вы могли бы немного сократить шаблонный код, если вас не интересуют имена классов и следование существующим соглашениям modeladmin, это ваше дело.
- Это предполагает, что ваши первичные ключи безопасны для URL, вы увидите, что в коде modeladmin есть много дополнительных утилит, чтобы сделать все URL безопасными.
- После создания дочерней страницы пользователь вернется к списку администраторов НЕ-модели родительской страницы. Изменение этого может потребовать немало дополнительной работы, но приведенный выше код должен дать вам то, что вы хотите.