Wagtail - 添加 CSS 类或占位符以形成构建器字段 [英] Wagtail - adding CSS class or placeholder to form builder fields

查看:33
本文介绍了Wagtail - 添加 CSS 类或占位符以形成构建器字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 Wagtail 管理表单构建器将 css 类(用于列宽)和占位符文本添加到我的 Wagtail 表单字段中.我试过使用 wagtail.contrib.forms 和 wagtailstreamforms 包无济于事.

我知道它在这里说Wagtail表格是'不是 Django 表单的替代品.但是,如果没有这样的基本功能,它的实用性就会受到限制.

解决方案

以下解决方案是一种利用 Wagtail contrib 表单构建器向 UI 添加字段的方法,CMS 用户可以在其中添加自定义类和占位符字段.

实施

  • 假设您有一个与 Wagtail 表单生成器文档.
  • 首先,您需要向 FormField 模型添加一个新字段,在下面的示例中,我将其称为 field_classname,请记住运行 Django 迁移以更新您的数据库.
  • 为确保该字段显示在管理 UI 中,您需要修改 panels,这类似于修改 Page 模型中的面板.立>
  • 此时,您应该能够打开 FormPage 的管理 UI,并看到新字段并能够将值保存到其中.
  • 下一步是添加一个自定义 FormBuilder 类,该类扩展通常使用的类,然后在您的 FormPage 模型上通过 form_builder 将其设置为属性,这类似于 新字段可以按照文档中的描述添加.
  • CustomFormBuilder 将使用一个包装函数覆盖方法 get_create_field_function,该函数将返回生成的字段(将是 Django 字段实例).
  • 每个 Field 实例的返回值几乎相同,除了对 widget attrs 本质上是一个可以添加任何内容的字典.
  • 重要提示: 使用 class 属性会将类名添加到字段中,但可能不会将其添加到您想要的位置,不过请先尝试.
  • 假设您对模板渲染有更精细的控制,您需要将此属性传递给渲染的每个字段 div 的模板,在下面的代码中我使用了相同的 field_classname 键.
  • 模板中的关键更改是拉出由我们的 CustomFormBuilder 设置的小部件 attrs 自定义值 -><div class="fieldWrapper {{ field.field.widget.attrs.field_classname }}";aria-required={% if field.field.required %}true"{% else %}false"{% endif %}>

models.py

从 django.db 导入模型从 modelcluster.fields 导入 ParentalKey从 wagtail.admin.edit_handlers 导入 FieldPanel从 wagtail.contrib.forms.forms 导入 FormBuilder从 wagtail.contrib.forms.models 导入 AbstractEmailForm, AbstractFormField# ... 其他进口类 FormField(AbstractFormField):page = ParentalKey("FormPage", related_name="form_fields", on_delete=models.CASCADE)# 向 FormField 模型添加自定义字段field_classname = models.CharField(字段类", max_length=254, blank=True)placeholder = models.CharField(Placeholder", max_length=254, blank=True)# 修改面板,以便可以在管理 UI 中编辑该字段面板 = AbstractFormField.panels + [FieldPanel("field_classname"),FieldPanel(占位符"),]类 CustomFormBuilder(FormBuilder):def get_create_field_function(self, type):"覆盖该方法以准备一个将调用原始函数的包装函数函数(返回一个字段)并使用自定义更新小部件的属性呈现每个字段时可以在模板中使用的值."create_field_function = super().get_create_field_function(type)defwrapped_create_field_function(field, options):created_field = create_field_function(字段,选项)created_field.widget.attrs.update(# {class": field.field_classname} # 重要提示:使用类可能就足够了,这取决于你的表单是如何呈现的,先试试这个.{"field_classname": field.field_classname} # 这是一个非标准属性,需要表单的自定义模板渲染才能工作{占位符":field.placeholder},)返回 created_field返回wrapped_create_field_function类 FormPage(AbstractEmailForm):form_builder = CustomFormBuilder # 使用自定义表单构建器覆盖行为# ... 其他表单页面字段、面板等

templates/form_page.html

{% 评论 %}您可以使用 Django 渲染快捷方式(例如 `{{ form.as_p }}`)来渲染表单,但这会导致代码缺乏语义,并且难以设置样式.您可以在以下位置阅读有关 Django 表单的更多信息:https://docs.djangoproject.com/en/1.10/topics/forms/#form-rendering-options{% 结尾评论 %}<form action="{% pageurl page %}";方法=POST"角色=形式">{% csrf_token %}{% if form.subject.errors %}<ol角色=警报对话框">{% for error in form.subject.errors %}<li role=alert"><strong>{{ error|escape }}</strong></li>{% 结束为 %}</ol>{% 万一 %}{% 用于表单 %} 中的字段<div class="fieldWrapper {{field.field.widget.attrs.field_classname }}";aria-required={% if field.field.required %}true"{% else %}false"{% endif %}>{{ field.label_tag }}{% if field.field.required %}*{% endif %}{{ 场地 }}{% if field.help_text %}<p class="help">{{ field.help_text|safe }}</p>{% 万一 %}

{% 结束为 %}<输入类型=提交"></表单>

I'm trying to add css classes (for column width) and placeholder text to my Wagtail form fields via the Wagtail admin form builder. I've tried using wagtail.contrib.forms and also the wagtailstreamforms package to no avail.

I know it says here that the Wagtail forms aren't a replacement for Django forms. However, without such basic functionality it's limited in its usefulness.

解决方案

The below solution is a way to leverage the Wagtail contrib form builder to add a field to the UI where CMS users can add custom classes and a placeholder field.

Implementation

  • It is assumed you have a working FormPage similar to the implementation in the Wagtail form builder docs.
  • Firstly, you will need to add a new field to the FormField model, in the example below I have called this field_classname, remember to run Django migrations to update your DB.
  • To ensure that the field shows up in the admin UI you will need to modify the panels, this is similar to modifying the panels in a Page model.
  • At this point you should be able to open the Admin UI for a FormPage and see the new field and be able to save values to it.
  • Next step is to add a custom FormBuilder class that extends the one that is normally used and then on your FormPage model set this as an attribute via form_builder, this is similar to how new fields can be added as described in the docs.
  • This CustomFormBuilder will override the method get_create_field_function with a wrapper function that will return the generated field (which will be a Django Field instance).
  • Each Field instance will be returned almost the same, except for an update to the widget attrs which is essentially a Dict that you can add anything to.
  • IMPORTANT: Using the class attr will add the class name to the field but may not add it where you want, try this first though.
  • Assuming you have more granular control of your template rending, you will need to pass this attr to the template for each field div that is rendered, in the code below I have used the same field_classname key.
  • The critical change in the template is pulling out the widget attrs custom value set by our CustomFormBuilder -> <div class="fieldWrapper {{ field.field.widget.attrs.field_classname }}" aria-required={% if field.field.required %}"true"{% else %}"false"{% endif %}>

models.py

from django.db import models

from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.contrib.forms.forms import FormBuilder
from wagtail.contrib.forms.models import AbstractEmailForm, AbstractFormField

# ... other imports


class FormField(AbstractFormField):

    page = ParentalKey("FormPage", related_name="form_fields", on_delete=models.CASCADE)
    
    # add custom fields to FormField model
    field_classname = models.CharField("Field classes", max_length=254, blank=True)
    placeholder = models.CharField("Placeholder", max_length=254, blank=True)
    
    # revise panels so that the field can be edited in the admin UI
    panels = AbstractFormField.panels + [
        FieldPanel("field_classname"),
        FieldPanel("placeholder"),
    ]


class CustomFormBuilder(FormBuilder):
    def get_create_field_function(self, type):
        """
        Override the method to prepare a wrapped function that will call the original
        function (which returns a field) and update the widget's attrs with a custom
        value that can be used within the template when rendering each field.
        """

        create_field_function = super().get_create_field_function(type)

        def wrapped_create_field_function(field, options):

            created_field = create_field_function(field, options)
            created_field.widget.attrs.update(
                # {"class": field.field_classname} # Important: using the class may be sufficient, depending on how your form is being rendered, try this first.
                {"field_classname": field.field_classname} # this is a non-standard attribute and will require custom template rendering of your form to work
                {"placeholder": field.placeholder},
            )

            return created_field

        return wrapped_create_field_function


class FormPage(AbstractEmailForm):
    form_builder = CustomFormBuilder  # use custom form builder to override behaviour

    # ... other form page fields, panels etc

templates/form_page.html

{% comment %}
You could render your form using a Django rendering shortcut such as `{{ form.as_p }}` but that will tend towards unsemantic code, and make it difficult to style. You can read more on Django form at:
https://docs.djangoproject.com/en/1.10/topics/forms/#form-rendering-options
{% endcomment %}
<form action="{% pageurl page %}" method="POST" role="form">
    {% csrf_token %}
    {% if form.subject.errors %}
        <ol role="alertdialog">
        {% for error in form.subject.errors %}
            <li role="alert"><strong>{{ error|escape }}</strong></li>
        {% endfor %}
        </ol>
    {% endif %}

    {% for field in form %}
        <div class="fieldWrapper {{ field.field.widget.attrs.field_classname }}" aria-required={% if field.field.required %}"true"{% else %}"false"{% endif %}>
            
            {{ field.label_tag }}{% if field.field.required %}<span class="required">*</span>{% endif %}

            {{ field }}
            
            {% if field.help_text %}
                <p class="help">{{ field.help_text|safe }}</p>
            {% endif %}
        </div>
    {% endfor %}

    <input type="submit">
</form>

这篇关于Wagtail - 添加 CSS 类或占位符以形成构建器字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆