一个 Wagtail 模型的多个 ModelAdmins
Multiple ModelAdmins for one Wagtail model
假设我有一个模型:
class BlogPost(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = StreamField([
('paragraph', blocks.RichTextBlock()),
('image', ImageChooserBlock()),
('gallery', CarouselBlock()),
('video', EmbedBlock()),
])
...
我想在侧边栏中创建多个与此模型相关的页面。我试过这样的方法:
class BlogPostAdmin(ModelAdmin):
model = BlogPost
...
class DraftPostAdmin(ModelAdmin):
model = BlogPost
#query for drafts
...
class ScheduledPostAdmin(ModelAdmin):
model = BlogPost
#query for scheduled posts
...
class BlogGroup(ModelAdminGroup):
menu_label = 'Blog'
items = (BookAdmin, AuthorAdmin, GenreAdmin)
...
modeladmin_register(BlogGroup)
但问题是所有页面都显示与第一个 ModelAdmin 的查询集匹配的模型实例。在 Wagtail 中实现多个菜单项以管理一个模型的不同方面的最佳方法是什么?
使用 proxy model and then define an appropriate manager for each proxy model. I have this working in an existing Wagtail-based application where I define proxy models for various states of Memberships in a membership application. In my case the base model is Member
, but then I have CurrentMember
, NonCurrentMember
, etc. This comment 相关讨论可能也很有趣。
这里有一个稍微不同的方法,通过重写 BlogGroup
上的一些方法并只使用一个 BlogPostAdmin
你可以走得更远。
代码
from wagtail.admin.menu import MenuItem
from wagtail.contrib.modeladmin.options import (
ModelAdmin, ModelAdminGroup, modeladmin_register)
from bakerydemo.blog.models import BlogPage
class ModelAdminQueryMenuItem(MenuItem):
# based on the `ModelAdminMenuItem` but extends the Wagtail Admin `MenuItem` directly.
def __init__(self, model_admin, order, query, label_append=''):
self.model_admin = model_admin
url = model_admin.url_helper.index_url + "?" + query
classnames = 'icon icon-%s' % model_admin.get_menu_icon()
super().__init__(
label=model_admin.get_menu_label() + label_append,
url=url,
classnames=classnames,
order=order
)
def is_shown(self, request):
return self.model_admin.permission_helper.user_can_list(request.user)
class BlogPageAdmin(ModelAdmin):
model = BlogPage
def get_menu_items(self, order=None):
# new class method that builds a list of menu_item(s)
menu_items = []
## build 'live only' (no unpublished changes) items
live_menu_item = ModelAdminQueryMenuItem(self, order or self.get_menu_order(), query='has_unpublished_changes=False', label_append=' (Live)')
menu_items.append(live_menu_item)
## build 'draft' items
draft_menu_item = ModelAdminQueryMenuItem(self, order or self.get_menu_order(), query='has_unpublished_changes=True', label_append=' (Draft)')
menu_items.append(draft_menu_item)
return menu_items
def get_queryset(self, request):
qs = super().get_queryset(request)
## read the request and modify the qs as needed if query param does not work easily
return qs
class BlogGroup(ModelAdminGroup):
menu_label = 'Blog'
items = (BlogPageAdmin, )
def get_submenu_items(self):
menu_items = []
item_order = 1
for modeladmin in self.modeladmin_instances:
menu_items = menu_items + modeladmin.get_menu_items(item_order)
item_order = len(menu_items) + 1
return menu_items
modeladmin_register(BlogGroup)
说明
- 设置单个
BlogPageAdmin
class,这将有一个新方法 get_menu_items
(复数),它将 return Wagtail 菜单项列表.
- 我们通过覆盖 Wagtail 管理 class
MenuItem
来生成这些菜单项,但我们还添加了一个用户权限助手,请参阅 modeladmin 中的 menus.py 助手文件。这为我们提供了一种自定义 URL(添加 url 参数)和标签的方法,这可以根据需要进行修改,以使我们的 sub-menu 项目以我们想要的方式呈现。
get_menu_items
手动构建我们想要的所有菜单项,我们可以在这里自定义任何内容,包括标签和图标以显示您想要的内容,本质上虽然这只是提供了一种传递自定义查询参数的方法字符串到 url 得到建立。
- 查询参数可以是我们想要的任何东西,搜索字符串和
Page
上的许多字段都可以使用而无需任何代码更改,因为它们只是作为字典传递到我们的查询中。下面我列出了所有可能的值。
- 对于其他更具体的内容,我们需要覆盖方法
get_queryset
并读取请求参数并相应地更新我们的查询。
- 您需要自定义视图的页面标题,但这可以通过阅读视图模板自定义中的请求或进一步自定义已构建的 url 来完成。
- 最后,在我们的
BlogGroup
中,我们覆盖 get_submenu_items
以使用自定义方法 get_menu_items
。请注意,这假定传递给该组的每个模型都将具有该方法。
查询字符串字段
- 选择有:blog_person_relationship、body、content_type、content_type_id、date_published、深度、draft_title、expire_at, 过期, first_published_at, 表单提交, go_live_at, group_permissions, has_unpublished_changes, id, image, image_id, 介绍, last_published_at, latest_revision_created_at, live, live_revision, live_revision_id, locked, numchild, owner, owner_id, page_ptr, page_ptr_id, path, redirect, revisions , search_description, searchpromotion, seo_title, show_in_menus, sites_rooted_here, slug, 副标题, tagged_items, 标签, 标题, url_path, view_restrictions
假设我有一个模型:
class BlogPost(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = StreamField([
('paragraph', blocks.RichTextBlock()),
('image', ImageChooserBlock()),
('gallery', CarouselBlock()),
('video', EmbedBlock()),
])
...
我想在侧边栏中创建多个与此模型相关的页面。我试过这样的方法:
class BlogPostAdmin(ModelAdmin):
model = BlogPost
...
class DraftPostAdmin(ModelAdmin):
model = BlogPost
#query for drafts
...
class ScheduledPostAdmin(ModelAdmin):
model = BlogPost
#query for scheduled posts
...
class BlogGroup(ModelAdminGroup):
menu_label = 'Blog'
items = (BookAdmin, AuthorAdmin, GenreAdmin)
...
modeladmin_register(BlogGroup)
但问题是所有页面都显示与第一个 ModelAdmin 的查询集匹配的模型实例。在 Wagtail 中实现多个菜单项以管理一个模型的不同方面的最佳方法是什么?
使用 proxy model and then define an appropriate manager for each proxy model. I have this working in an existing Wagtail-based application where I define proxy models for various states of Memberships in a membership application. In my case the base model is Member
, but then I have CurrentMember
, NonCurrentMember
, etc. This comment 相关讨论可能也很有趣。
这里有一个稍微不同的方法,通过重写 BlogGroup
上的一些方法并只使用一个 BlogPostAdmin
你可以走得更远。
代码
from wagtail.admin.menu import MenuItem
from wagtail.contrib.modeladmin.options import (
ModelAdmin, ModelAdminGroup, modeladmin_register)
from bakerydemo.blog.models import BlogPage
class ModelAdminQueryMenuItem(MenuItem):
# based on the `ModelAdminMenuItem` but extends the Wagtail Admin `MenuItem` directly.
def __init__(self, model_admin, order, query, label_append=''):
self.model_admin = model_admin
url = model_admin.url_helper.index_url + "?" + query
classnames = 'icon icon-%s' % model_admin.get_menu_icon()
super().__init__(
label=model_admin.get_menu_label() + label_append,
url=url,
classnames=classnames,
order=order
)
def is_shown(self, request):
return self.model_admin.permission_helper.user_can_list(request.user)
class BlogPageAdmin(ModelAdmin):
model = BlogPage
def get_menu_items(self, order=None):
# new class method that builds a list of menu_item(s)
menu_items = []
## build 'live only' (no unpublished changes) items
live_menu_item = ModelAdminQueryMenuItem(self, order or self.get_menu_order(), query='has_unpublished_changes=False', label_append=' (Live)')
menu_items.append(live_menu_item)
## build 'draft' items
draft_menu_item = ModelAdminQueryMenuItem(self, order or self.get_menu_order(), query='has_unpublished_changes=True', label_append=' (Draft)')
menu_items.append(draft_menu_item)
return menu_items
def get_queryset(self, request):
qs = super().get_queryset(request)
## read the request and modify the qs as needed if query param does not work easily
return qs
class BlogGroup(ModelAdminGroup):
menu_label = 'Blog'
items = (BlogPageAdmin, )
def get_submenu_items(self):
menu_items = []
item_order = 1
for modeladmin in self.modeladmin_instances:
menu_items = menu_items + modeladmin.get_menu_items(item_order)
item_order = len(menu_items) + 1
return menu_items
modeladmin_register(BlogGroup)
说明
- 设置单个
BlogPageAdmin
class,这将有一个新方法get_menu_items
(复数),它将 return Wagtail 菜单项列表. - 我们通过覆盖 Wagtail 管理 class
MenuItem
来生成这些菜单项,但我们还添加了一个用户权限助手,请参阅 modeladmin 中的 menus.py 助手文件。这为我们提供了一种自定义 URL(添加 url 参数)和标签的方法,这可以根据需要进行修改,以使我们的 sub-menu 项目以我们想要的方式呈现。 get_menu_items
手动构建我们想要的所有菜单项,我们可以在这里自定义任何内容,包括标签和图标以显示您想要的内容,本质上虽然这只是提供了一种传递自定义查询参数的方法字符串到 url 得到建立。- 查询参数可以是我们想要的任何东西,搜索字符串和
Page
上的许多字段都可以使用而无需任何代码更改,因为它们只是作为字典传递到我们的查询中。下面我列出了所有可能的值。 - 对于其他更具体的内容,我们需要覆盖方法
get_queryset
并读取请求参数并相应地更新我们的查询。 - 您需要自定义视图的页面标题,但这可以通过阅读视图模板自定义中的请求或进一步自定义已构建的 url 来完成。
- 最后,在我们的
BlogGroup
中,我们覆盖get_submenu_items
以使用自定义方法get_menu_items
。请注意,这假定传递给该组的每个模型都将具有该方法。
查询字符串字段
- 选择有:blog_person_relationship、body、content_type、content_type_id、date_published、深度、draft_title、expire_at, 过期, first_published_at, 表单提交, go_live_at, group_permissions, has_unpublished_changes, id, image, image_id, 介绍, last_published_at, latest_revision_created_at, live, live_revision, live_revision_id, locked, numchild, owner, owner_id, page_ptr, page_ptr_id, path, redirect, revisions , search_description, searchpromotion, seo_title, show_in_menus, sites_rooted_here, slug, 副标题, tagged_items, 标签, 标题, url_path, view_restrictions