如何修改Wagtail表单输入字段的属性?

Nar*_*asK 2 django django-forms wagtail

我正在查看wagtail hello-world 表单 示例:

class FormField(AbstractFormField):
    page = ParentalKey('FormPage', related_name='form_fields')


class FormPage(AbstractEmailForm):
    landing_page_template = 'blog/form_page.html'
    intro = RichTextField(blank=True)
    thank_you_text = RichTextField(blank=True)

    content_panels = AbstractEmailForm.content_panels + [
        FormSubmissionsPanel(),
        FieldPanel('intro', classname="full"),
        InlinePanel('form_fields', label="Form fields"),
        FieldPanel('thank_you_text', classname="full"),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email"),
    ]
Run Code Online (Sandbox Code Playgroud)

如果给出这样的模板:

{% for field in form %}
  {{ field }} 
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

它将呈现类似于以下内容的 HTML:

<input type="text" name="label1" value="Default Label1" required maxlength="255" id="id_label1" />
<input type="url" name="label2" value="http://Label2.net" id="id_label2" />
<textarea name="label3" required rows="10" id="id_label3" cols="40">
Run Code Online (Sandbox Code Playgroud)

如何修改/向呈现的输入字段添加额外的属性?

例如:

  • 如何添加class="form-control"?
  • 如何rows="5"在textarea输入中更改?

除了javascript疯狂之外还有其他方便的方法吗?

LB *_*ton 10

我假设您想要更改FormPage's 的呈现方式(即扩展AbstractEmailForm或 的页面AbstractForm)。

有一些方法可以从form_page.html模板中执行此操作(请参阅答案底部的链接),但是,我认为最好的办法是在这些属性进入模板之前添加它们。

这样你就可以让你的模板非常简单,即使只是使用文档示例中的复制和粘贴。

{% load wagtailcore_tags %}
<html>
    <head>
        <title>{{ page.title }}</title>
    </head>
    <body>
        <h1>{{ page.title }}</h1>
        {{ page.intro|richtext }}
        <form action="{% pageurl page %}" method="POST">
            {% csrf_token %}
            {{ form.as_p }}
            <input type="submit">
        </form>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

然后,在my_app/models.py你想覆盖get_form的方法对你FormPage。您可以get_form在 Wagtail form/models.py 代码中查看该方法的作用。

您需要确保form通过 super获取生成的对象。然后遍历字段 - 更新每个字段上的小部件。小部件用于呈现输入字段(或 Textarea),默认情况下,Textarea 小部件包含 10 行和 40 列。

您还可以attrs使用class键更新任何小部件上的字典,以将自定义类添加到呈现的输入中。这样我们就可以添加form-control到每个输入中。

见示例:

from django.forms import widgets  # used to find TextArea widget
# other imports.... AbstractEmailForm etc

class FormPage(AbstractEmailForm):
    # body, thank_you_text, etc

    def get_form(self, *args, **kwargs):
        form = super().get_form(*args, **kwargs)
        # form = super(AbstractEmailForm, self).get_form(*args, **kwargs)  # use this syntax for Python 2.x
        # iterate through the fields in the generated form
        for name, field in form.fields.items():
            # here we want to adjust the widgets on each field
            # if the field is a TextArea - adjust the rows
            if isinstance(field.widget, widgets.Textarea):
                field.widget.attrs.update({'rows': '5'})
            # for all fields, get any existing CSS classes and add 'form-control'
            # ensure the 'class' attribute is a string of classes with spaces
            css_classes = field.widget.attrs.get('class', '').split()
            css_classes.append('form-control')
            field.widget.attrs.update({'class': ' '.join(css_classes)})
        return form
Run Code Online (Sandbox Code Playgroud)

这将在 html 属性中呈现所有textarea 输入,rows=5并且还会添加form-control到class所有输入的属性中(如果使用的话,甚至是隐藏输入)。请记住,这将改变FormPage使用中的每一个。

对于模板中更复杂的表单渲染,这篇文章非常好,但它非常完整:https : //simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually。 html#accessing-the-form-fields-individually

此外,对于基本的 Bootstrap 3(或 4)表单渲染,Crispy Forms可能会为您省去很多麻烦。