跳转到主要内容

一个基于Torchbox风格的django-crispy-forms模板包,改编自crispy-forms-gds

项目描述

PyPI npm PyPI downloads CI

Torchbox表单

一个基于Torchbox风格的django-crispy-forms模板包,改编自crispy-forms-gds

默认情况下,使用 tbxforms 创建的表单将类似于 GOV.UK 设计系统,尽管可以自定义许多变量。

要求

  • python >=3.8.1,<4.0
  • Django >=3.2
  • django-crispy-forms >=2.1,<3.0
  • 如果使用 WagtailBaseForm,则需要 wagtail >=2.15
  • 如果自行构建 Sass,则需要 sass >=1.33.0

[!注意] govuk-frontend 不需要安装即可使用此包。

已将 govuk-frontend==5.4.1 中的所有表单相关样式复制到此项目,将“govuk-”前缀替换为“tbxforms-”,例如,.govuk-button 更改为 .tbxforms-button,以及 @mixin govuk-clearfix 更改为 @mixin tbxforms-clearfix

对于非政府项目,无需安装完整的 GOV.UK 前端包,因为我们只需要表单相关样式。

对于政府项目,这会增加包的大小,因为必须安装 tbxformsgovuk-frontend。然而,这些项目较少见,因此没有优先考虑。

安装

您必须安装 Python 包和 NPM 包。

安装 Python 包

使用 pip 安装

pip install tbxforms

django-crispy-formstbxforms 添加到您的已安装应用中

INSTALLED_APPS = [
  # ...
  'crispy_forms',  # django-crispy-forms
  'tbxforms',
]

现在添加以下设置,告诉 django-crispy-forms 使用 tbxforms

CRISPY_ALLOWED_TEMPLATE_PACKS = ["tbx"]
CRISPY_TEMPLATE_PACK = "tbx"

安装 NPM 包

使用 NPM 安装

npm install tbxforms

注意:此包使用 Element.closestNodeList.forEachArray.includes API。如果您需要支持旧版浏览器,则需要安装和配置 polyfills。

实例化您的表单

import TbxForms from 'tbxforms';

document.addEventListener('DOMContentLoaded', () => {
    for (const form of document.querySelectorAll(TbxForms.selector())) {
        new TbxForms(form);
    }
});

将样式导入到您的项目中...

...作为无任何自定义的 CSS

@use 'node_modules/tbxforms/dist/style.css';

...或作为 Sass 以自定义变量

@use 'node_modules/tbxforms/tbxforms.scss' with (
    $tbxforms-text-colour: #000,
    $tbxforms-error-colour: #f00,
);

添加按钮样式

tbxforms 为除按钮之外的所有内容提供默认的 GOV.UK 设计系统样式,因为这些样式可能已经存在于您的项目中。

您需要为以下类编写按钮样式

  1. .tbxforms-button
  2. .tbxforms-button.tbxforms-button--primary
  3. .tbxforms-button.tbxforms-button--secondary
  4. .tbxforms-button.tbxforms-button--warning

用法

tbxforms 可用于编码的 Django 表单和编辑器控制的 Wagtail 表单。

Django 表单

所有表单都必须继承 TbxFormsMixin 混合,同时指定 Django 基础表单类(例如 forms.Formforms.ModelForm

from django import forms
from tbxforms.forms import TbxFormsMixin

class ExampleForm(TbxFormsMixin, forms.Form):
    ...

class ExampleModelForm(TbxFormsMixin, forms.ModelForm):
    ...

Wagtail 表单

创建或更新一个 Wagtail 表单

Wagtail 表单必须继承 TbxFormsMixinWagtailBaseForm

from wagtail.contrib.forms.forms import BaseForm as WagtailBaseForm
from tbxforms.forms import TbxFormsMixin

class ExampleWagtailForm(TbxFormsMixin, WagtailBaseForm):
    ...

指示一个 Wagtail 页面模型使用您的表单

在您的表单定义中(例如 forms.py)

from tbxforms.forms import BaseWagtailFormBuilder as TbxFormsBaseWagtailFormBuilder
from path.to.your.forms import ExampleWagtailForm

class WagtailFormBuilder(TbxFormsBaseWagtailFormBuilder):
    def get_form_class(self):
        return type(str("WagtailForm"), (ExampleWagtailForm,), self.formfields)

并在您的表单页面模型中(例如 models.py)

from path.to.your.forms import WagtailFormBuilder

class ExampleFormPage(...):
    ...
    form_builder = WagtailFormBuilder
    ...

渲染表单

与 Django Crispy Forms 一样,您需要将表单对象传递给 {% crispy ... %} 模板标签,例如。

{% load crispy_forms_tags %}

<html>
    <body>
        {% crispy your_sexy_form %}
    </body>
</html>

FormHelper

FormHelper 允许您更改表单的渲染行为。

继承自 TbxFormsMixin 的每个表单(即 tbxforms 中的每个表单)都将具有以下默认属性 FormHelper

  • html5_required = True
  • label_size = Size.MEDIUM
  • legend_size = Size.MEDIUM
  • form_error_title = _("There is a problem with your submission")
  • 以及来自 django-crispy-forms 的默认属性

这些可以在实例化期间更改,或 即时更改 - 下面的示例。

添加提交按钮

提交按钮不会自动添加到表单中。要添加一个,您可以扩展 form.helper.layout(以下示例)。

在实例化期间扩展

from django import forms
from tbxforms.forms import TbxFormsMixin
from tbxforms.layout import Button

class YourSexyForm(TbxFormsMixin, forms.Form):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper.layout.extend([
            Button.primary(
                name="submit",
                type="submit",
                value="Submit",
            )
        ])

或之后扩展

from tbxforms.layout import Button

form = YourSexyForm()
form.helper.layout.extend([
    Button.primary(
        name="submit",
        type="submit",
        value="Submit",
    )
])

条件性必填字段

tbxforms可以根据给定值显示/隐藏layout的部分。例如,当用户选择订阅通讯时(以下为示例),您可以只显示(并要求)电子邮件地址字段。

您可以将此逻辑应用于fielddivfieldset元素。

注意:在conditional_fields_to_show_as_required()方法中包含的任何字段名称将作为必填项显示在前端,尽管技术上required=False

字段示例

from django import forms
from django.core.exceptions import ValidationError
from tbxforms.choices import Choice
from tbxforms.forms import TbxFormsMixin
from tbxforms.layout import Field, Layout

class ExampleForm(TbxFormsMixin, forms.Form):
    NEWSLETTER_CHOICES = (
        Choice("yes", "Yes please", hint="Receive occasional email newsletters."),
        Choice("no", "No thanks"),
    )

    newsletter_signup = forms.ChoiceField(
        choices=NEWSLETTER_CHOICES
    )

    email = forms.EmailField(
        widget=forms.EmailInput(required=False)
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper.layout = Layout(
            # Add our newsletter sign-up field.
            Field.text("newsletter_signup"),

            # Add our email field and define the conditional logic.
            Field.text(
                "email",
                data_conditional={
                    "field_name": "newsletter_signup", # Field to inspect.
                    "values": ["yes"], # Value(s) to cause this field to show.
                },
            ),
        )

    @staticmethod
    def conditional_fields_to_show_as_required() -> [str]:
        # Non-required fields that should show as required to the user.
        return [
            "email",
        ]

    def clean(self):
        cleaned_data = super().clean()
        newsletter_signup = cleaned_data.get("newsletter_signup")
        email = cleaned_data.get("email")

        # Fields included within `conditional_fields_to_show_as_required()` will
        # be shown as required but not enforced - i.e. they will not have the
        # HTML5 `required` attribute set.
        # Thus we need to write our own check to enforce the value exists.
        if newsletter_signup == "yes" and not email:
            raise ValidationError(
                {
                    "email": "This field is required.",
                }
            )
        # The tbxforms JS will attempt to clear any redundant data upon submission,
        # though it is recommended to also handle this in your clean() method.
        elif newsletter_signup == "no" and email:
            del cleaned_data['email']

        return cleaned_data

容器示例

当您想一起显示/隐藏多个字段/元素时,您可以在divfieldset元素上使用与上面相同的data_conditional定义,例如:

from tbxforms.layout import HTML, Div, Field, Layout

Layout(
    Div(
        HTML("<p>Some relevant text.</p>"),
        Field.text("some_other_field"),
        Field.text("email"),
        data_conditional={
            "field_name": "newsletter_signup",
            "values": ["yes"],
        },
    ),
)

自定义行为

突出显示必填项而不是可选项

如果TBXFORMS_HIGHLIGHT_REQUIRED_FIELDS=False(或未设置),则可选字段将附加“(可选)”到其标签。这是默认行为,并被GDS推荐。

如果TBXFORMS_HIGHLIGHT_REQUIRED_FIELDS=True,则必填字段将附加星号到其标签,而可选字段将不会突出显示。

您还可以通过针对这些CSS类来设置这些标记的样式

  • .tbxforms-field_marker--required
  • .tbxforms-field_marker--optional

更改默认标签和图例类

label_sizelegend_size的可能值

  1. (默认值)
  2. 超大

进一步阅读

项目详情


下载文件

下载适合您平台文件的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

tbxforms-3.0.0.tar.gz (62.3 kB 查看哈希)

上传时间

构建分布

tbxforms-3.0.0-py3-none-any.whl (89.3 kB 查看哈希)

上传时间 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面