如何自定义Wagtail Generic Chooser视图并修复多选框显示异常
解决Wagtail文章片段选择器复选框显示异常问题
当前文章片段选择器无法正确渲染多选字段(分类、国家)的复选框,需要通过重写选择器的基础视图来修复。
现有代码
ArticleChooserMixin 与 ArticleChooserViewSet
class ArticleChooserMixin(ModelChooserMixin): def get_edit_item_url(self, item): # for Wagtail 4.x return reverse( "wagtailsnippets_app_name_article:edit", args=(quote(item.pk),) ) class ArticleChooserViewSet(ModelChooserViewSet): icon = "user" model = Article page_title = _("选择文章") per_page = 10 order_by = "title" fields = ["title", "body", "url", "categories", "countries"] chooser_mixin_class = ArticleChooserMixin
Article模型部分代码
from dal import autocomplete ... @register_snippet class Article( DraftStateMixin, RevisionMixin, index.Indexed, ClusterableModel, Orderable, SourceDataMixin, ): ... categories = ParentalManyToManyField("app_name.ArticleCategory", blank=True) countries = ParentalManyToManyField("app_name.Country", blank=True) ... FieldPanel("categories", widget=autocomplete.ModelSelect2Multiple()) FieldPanel("countries", widget=autocomplete.ModelSelect2Multiple()), ...
问题说明
- 期望效果:片段创建视图中,分类、国家这类多选字段以带复选框的选择器正常显示
- 当前问题:多选字段的复选框无法正确渲染,显示异常
- 参考:wagtail-generic-chooser项目的Issue #65
解决方案
Wagtail通用选择器默认不兼容autocomplete.ModelSelect2Multiple这类第三方组件,需要替换为Wagtail原生支持的多选widget来修复显示问题,以下是两种实现方式:
方式一:自定义选择器表单
导入所需模块后定义适配的表单类,再在ViewSet中指定该表单:
from wagtail.admin.widgets import AdminTagWidget from wagtail.generic_chooser.views import ModelChooserForm # 自定义选择器表单 class ArticleChooserForm(ModelChooserForm): class Meta: model = Article fields = ["title", "body", "url", "categories", "countries"] widgets = { "categories": AdminTagWidget(model=ArticleCategory), "countries": AdminTagWidget(model=Country), } # 修改ArticleChooserViewSet class ArticleChooserViewSet(ModelChooserViewSet): icon = "user" model = Article page_title = _("选择文章") per_page = 10 order_by = "title" fields = ["title", "body", "url", "categories", "countries"] chooser_mixin_class = ArticleChooserMixin form_class = ArticleChooserForm # 指定自定义表单
方式二:重写get_form方法动态替换组件
直接在ViewSet中重写get_form方法,替换多选字段的widget:
from wagtail.admin.widgets import AdminTagWidget class ArticleChooserViewSet(ModelChooserViewSet): icon = "user" model = Article page_title = _("选择文章") per_page = 10 order_by = "title" fields = ["title", "body", "url", "categories", "countries"] chooser_mixin_class = ArticleChooserMixin def get_form(self, request, *args, **kwargs): form = super().get_form(request, *args, **kwargs) # 替换为Wagtail原生AdminTagWidget form.fields["categories"].widget = AdminTagWidget(model=ArticleCategory) form.fields["countries"].widget = AdminTagWidget(model=Country) return form
说明
AdminTagWidget是Wagtail原生的多选选择组件,能够正确渲染符合后台样式的选择界面(包含复选框或标签式选择),与片段创建视图的显示效果一致。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

