我有一个 wagtail 管理表单,我想在其中自定义用于填充 ManyToMany 字段的一系列复选框选项的布局。我正在编辑的模型称为“产品”;该字段是“displays_on_pages”,它链接到一个单独的“GenericPage”模型。问题是,我有很多这些页面作为选项可用,这使得将它们显示为常规的复选框列表有点笨拙。我想将它们嵌套显示,以便我可以在其父页面下缩进子页面。像这样的东西:
□ Parent Page 1
□ Subpage 1.1
□ Subpage 1.1.1
□ Subpage 1.2
□ Parent Page 2
□ Subpage 2.1
(etc.)
我已经弄清楚如何通过子类化 forms.widgets.CheckboxSelectMultiple 创建自定义表单小部件,如何传入我自己的查询逻辑,以便可作为复选框小部件选择的页面显示为树,以及如何设置输出模板。问题是我传递给模板的选择似乎不是实际的“页面”对象。当我遍历查询集时,我可以获得每个选项的值(id)和标签(标题),但我似乎无法使用“特定”来获取其他“页面”模型属性,例如“路径”或“深度”。尝试在模板中输出类似 {{ option.specific.depth }} 的内容只是空的。我想做的是在其中扔一些 CSS 来根据每个选项的深度来识别每个选项,例如 style="padding-left: 20px;" 如果深度为 2,style="padding-left: 40px;" 如果深度为 3,等等。
以下是 models.py 中的相关类:
class ProductPageSelectInput(forms.widgets.CheckboxSelectMultiple):
template_name = 'forms/product_page_select.html'
def get_context(self, name, value, attrs):
context = super(ProductPageSelectInput, self).get_context(name, value, attrs)
return context
#custom field panel to allow selection of pages to list products on
class ProductPageSelectPanel(FieldPanel):
def on_form_bound(self):
choices = self.model.get_page_choices(self.model)
self.form.fields['displays_on_pages'].queryset = choices
self.form.fields['displays_on_pages'].empty_label = None
super().on_form_bound()
class Product(Page):
product_description = RichTextField(features=RICH_TEXT_FIELD_FEATURES,null=True,blank=True)
displays_on_pages = ParentalManyToManyField('GenericPage', blank=True)
def get_page_choices(self):
return GenericPage.objects.live()
content_panels = [
FieldPanel('title'),
FieldPanel('product_description'),
ProductPageSelectPanel('displays_on_pages',widget=ProductPageSelectInput),
]
以下是模板“forms/product_page_select.html”中的内容:
<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>
{% for group, options, index in widget.optgroups %}
{% if group %}{{ group }}<div{% if id %} id="{{ id }}_{{ index }}"{% endif %}>{% endif %}
{% for option in options %}
<div id="product_page_div">{% include 'forms/product_page_option.html' with widget=option %}</div>
{% endfor %}
{% if group %}</div>{% endif %}
{% endfor %}
</div>
{% endwith %}
在“product_page_div”内部,我想根据页面深度做一些有条件的事情,我需要弄清楚如何引用它(或如何重新定义传入的查询集以使其包含该信息) .
以下是包含的模板“forms/product_page_option.html”的内容:
{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "forms/product_page_input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
和“表单/product_page_input.html”:
<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}>
(最后两个基本上是从 Wagtail 核心的管理模板中复制和粘贴的。)