如何使用 Wagtail 挂钩在 Wagtail 中生成自定义 link

How to generate a custom link in Wagtail using Wagtail hooks

所以我想在 Wagtail 管理中添加一个额外的 link。我正在关注文档 (Register Admin Menu Item Hook) 并使用此挂钩构建一个新的菜单项。

他们使用这个钩子来添加菜单项:

@hooks.register('register_admin_menu_item')
def register_edit_menu_item():
    return MenuItem('Edit profile', 'edit_link', classnames='icon icon-folder-inverse', order=10000)

这应该成为 link,它开始编辑当前登录用户拥有的页面。在模板中,我使用此代码创建直接 link 来编辑用户的个人资料:

{% with request.user.owned_pages.all as pages %}
   {% if pages.exists %}
      {% for p in pages %}
         {% if p.get_parent.id == 17 %}
         <a class="list-group-item" href="/dashboard/pages/{{ p.id }}/edit/"><i class="fe-icon-edit mr-1 text-muted"></i>Edit profile</a>
         {% endif %}
      {% endfor %}
   {% endif %}
{% endwith %}

这工作正常,它 link 直接转到它应该 link 的页面。但是,如何实现这样的条件,根据当前登录用户生成菜单 link?

我会这样想:

if request.user.owned_pages.exists():
   for p in request.user.owned_pages.all():
      if p.get_parent.id == 17:
         edit_link = "/dashboard/pages/" + p.id + "/edit/"

但是我怎样才能在 Wagtail 菜单挂钩中实现这样的东西呢?

default implementation of MenuItem 假定 URL 在所有页面请求中保持不变,这意味着我们可以将固定的 URL 传递给 MenuItem 构造函数 register_admin_menu_item 钩子(在服务器启动时运行)。

在您的情况下,情况并非如此,因此您需要定义 MenuItem 的自定义子类。如果您查看 MenuItem 的代码,您会发现它实现了一个 get_context(self, request) 方法来收集呈现菜单项所需的所有模板变量,包括 url。您可以覆盖此方法以设置动态 URL 代替固定的

class EditProfileMenuItem(MenuItem):
    def get_context(self, request):
        context = super().get_context(request)

        edit_link = None
        if request.user.owned_pages.exists():
           for p in request.user.owned_pages.all():
              if p.get_parent().id == 17:
                 edit_link = "/dashboard/pages/" + p.id + "/edit/"

        if edit_link:
            context['url'] = edit_link

        return context

然后您可以在 register_admin_menu_item 挂钩中使用此子类,代替 MenuItem:

@hooks.register('register_admin_menu_item')
def register_edit_menu_item():
    return EditProfileMenuItem('Edit profile', 'edit_link', classnames='icon icon-folder-inverse', order=10000)

(根据您的要求,您可能还想重写 is_shown 方法,以便对没有配置文件的用户隐藏菜单项。)