wagtail - 如何将页面隐私复制到 Wagtail 中的 Block?
问题描述
页面具有此隐私设置,您可以在其中设置允许查看特定页面的人员。
我的文档需要更细粒度的控制,对于特定的块,也可以设置限制其可见性。
我会很满足于组选择器,但显然我不能在 Page 模型中放置 ManyToManyRelation。相反,我会在需要特别处理的块中进行。
所以我尝试像这样定义块:
class MyBlock(StructBlock):
visible_groups = ListBlock(ChooserBlock(
label=_('Limit view to groups'), target_model='django.contrib.auth.groups',
required=False, blank=True
))
但是 Wagtail 抱怨说选择器块被声明时没有 target_model 属性。我猜缺少构造函数这样做足以表明 ChooserBlock 本身不适用于这样的操作。
如何正确声明我的 Block 以便我可以选择组,然后在渲染时正确识别它们并将它们与用户组匹配?
解决方案
ChooserBlock
并不是要单独使用,而是要用于构建其他类型的选择器的基类。
选项 0 - 使用相关模型
- 虽然我理解您不想使用模型关系的愿望,但您最终可能会通过尝试在此处使用 StreamFields 来创建很多复杂性。
- 在基本关系方面重新考虑问题可能是值得的,您的页面作为内容项列表,每个内容项与身份验证组具有一对多的关系并且具有一些内容(富文本等)。
- 您可以使用与您的页面相关的普通模型来执行此操作,并使用 Wagtail 的InlinePanel允许用户创建许多这些内容项,每个内容项都有自己的身份验证组集和内容。请记住,其他模型上的内部内容仍然可以基于 StreamField,但此方法中的主要连接将是正常的 Django 关系。
- 请记住,StreamField 链接不是那么健壮(例如,如果 auth 组被删除,链接可能会在您的 StreamField 中变得陈旧,并且没有简单的方法来阻止它),如果您想在未来。
选项 1 - 使用SnippetChooser
最快的方法是使用SnippetChooserBlock
Django auth 组并将其注册为一个片段。这种方法的一个警告是,该模型将在管理 UI 的片段菜单(如果启用)中可见。
首先,将模型注册为中央某处的片段(例如wagtail_hooks.py
)
from django.contrib.auth.models import Group
from wagtail.snippets.models import register_snippet
# ... other hooks things
register_snippet(Group)
StructBlock
然后使用SnippetChooser
您保存 Blocks 的任何位置构建您的自定义。
from django.contrib.auth.models import Group
from wagtail.snippets.blocks import SnippetChooserBlock
from wagtail.core.blocks import ListBlock
class PrivacyBlock(StructBlock):
visible_groups = ListBlock(
SnippetChooserBlock(
Group,
label='Limit view to groups',
required=False,
blank=True
)
)
class Meta:
icon = "user"
最后,您可以像任何其他 StructBlock 一样在 PageModel 中使用它。
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, StreamFieldPanel
from wagtail.core.fields import StreamField
from myapp.blocks import PrivacyBlock
class BlogPage(Page):
# ... other fields
privacy_content = StreamField([
('privacy', PrivacyBlock(blank=True))
])
content_panels = Page.content_panels + [
# ... other panels
StreamFieldPanel('privacy_content'),
]
选项 2 - 构建或使用通用模型选择
您可以扩展 ChooserBlock 以构建您自己的选择器,但这会很快变得复杂,因为您还需要构建自定义模型选择器。下面的代码功能不完整,但可以让您了解可能需要什么。
如果您可以使用其他库,则可能值得考虑添加 Wagtail 通用选择器,这是来自 Google 的一些快速结果(我没有使用这些)。
- https://github.com/wagtail/wagtail-generic-chooser
- https://github.com/Naeka/wagtailmodelchooser/
- https://github.com/neon-jungle/wagtailmodelchooser
- https://github.com/springload/wagtailmodelchoosers
请记住,选择器块特定于 StreamField 实现,并且选择器类似于特定类型的 Django 小部件。如果您想为此实现使用 StreamFields,您将需要构建或获取两者。
如果您需要构建自己的,我建议您深入了解 Wagtail 的内部结构,以了解其他选择器是如何构建的。
- 选择器块 - https://github.com/wagtail/wagtail/blob/master/wagtail/core/blocks/field_block.py
- AdminChooser - https://github.com/wagtail/wagtail/blob/master/wagtail/admin/widgets.py
POC(非功能性)代码示例
from wagtail.admin.widgets import AdminChooser
from django.utils.functional import cached_property
class ModelChooser(AdminChooser):
# ... implement __init__ etc
class AuthGroupBlock(ChooserBlock):
@cached_property
def target_model(self):
from django.contrib.auth.models import Group
return Group
@cached_property
def widget(self):
return ModelChooser(self.target_model)
class PrivacyBlock(StructBlock):
visible_groups = ListBlock(
AuthGroupBlock(
label='Limit view to groups',
required=False,
blank=True
)
)
class Meta:
icon = "user"
class PrivacyBlock(StructBlock):
visible_groups = ListBlock(
SnippetChooserBlock(
Group,
label='Limit view to groups',
required=False,
blank=True
)
)
class Meta:
icon = "user"
推荐阅读
- excel - 使用 Google 脚本将 Google Sheet 导出到 Excel
- ios - 搜索栏未显示在导航栏 iOS 11 上
- javascript - 如何修改一组对象以按最近一年分组?
- r - 如何将两个相同的数据框组合在一起并在一列中替换一些值?
- lua - 用 lua 本身剖析 lua 代码
- mysql - mysql中的条件计数
- java - 从字符串中提取数字获取数字格式异常
- grafana - 在表格视图中创建具有特定单元格值的绝对链接
- nginx - 带有 web uwsgi 和 nginx 的烧瓶无法运行 index.html
- docker - 为使用 docker-compose 启动的 Rancher 2.x 的证书管理器创建颁发者