用Django Crispy Forms进行高级表单渲染的详细教程

1,160 阅读3分钟

在本教程中,我们将探索Django Crispy Forms的一些功能,以处理高级/定制表单的渲染。这篇博文是在我们的社区论坛上开始讨论的,所以我决定将这些见解和解决方案汇编成一篇博文,让更多的人受益。

简介

在本教程中,我们将使用Django APIs实现以下Bootstrap 4表单:

Bootstrap 4 Form

这是从Bootstrap 4的官方文档中摘取的,作为如何使用表单行的例子。

注意!

下面的例子指的是一个base.html 的模板。请考虑下面的代码。

base.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
  <div class="container">
    {% block content %}
    {% endblock %}
  </div>
</body>
</html>

安装

用pip安装它:

pip install django-crispy-forms

把它添加到你的INSTALLED_APPS ,并选择要使用的样式。

settings.py

INSTALLED_APPS = [
    ...

    'crispy_forms',
]

CRISPY_TEMPLATE_PACK = 'bootstrap4'

基本的表单渲染

表示上述表单所需的Python代码如下:

from django import forms

STATES = (
    ('', 'Choose...'),
    ('MG', 'Minas Gerais'),
    ('SP', 'Sao Paulo'),
    ('RJ', 'Rio de Janeiro')
)

class AddressForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    password = forms.CharField(widget=forms.PasswordInput())
    address_1 = forms.CharField(
        label='Address',
        widget=forms.TextInput(attrs={'placeholder': '1234 Main St'})
    )
    address_2 = forms.CharField(
        widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'})
    )
    city = forms.CharField()
    state = forms.ChoiceField(choices=STATES)
    zip_code = forms.CharField(label='Zip')
    check_me_out = forms.BooleanField(required=False)

在这种情况下,我使用了一个普通的Form ,但也可以是一个基于Django模型的ModelForm ,有类似的字段。state 字段和STATES 选择可以是外键或其他任何东西。这里我只是用一个简单的静态例子,有三个巴西状态。

模板:

{% extends 'base.html' %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    <table>{{ form.as_table }}</table>
    <button type="submit">Sign in</button>
  </form>
{% endblock %}

渲染的HTML:

Simple Django Form

带有验证状态的渲染的HTML:

Simple Django Form Validation State


基本的脆皮表单渲染

与之前的例子中的表单代码相同。

模板:

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    {{ form|crispy }}
    <button type="submit" class="btn btn-primary">Sign in</button>
  </form>
{% endblock %}

渲染的HTML:

Crispy Django Form

带有验证状态的渲染的HTML:

Crispy Django Form Validation State


用Crispy表格放置自定义字段

与第一个例子中的表单代码相同。

模板:

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.email|as_crispy_field }}
      </div>
      <div class="form-group col-md-6 mb-0">
        {{ form.password|as_crispy_field }}
      </div>
    </div>
    {{ form.address_1|as_crispy_field }}
    {{ form.address_2|as_crispy_field }}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.city|as_crispy_field }}
      </div>
      <div class="form-group col-md-4 mb-0">
        {{ form.state|as_crispy_field }}
      </div>
      <div class="form-group col-md-2 mb-0">
        {{ form.zip_code|as_crispy_field }}
      </div>
    </div>
    {{ form.check_me_out|as_crispy_field }}
    <button type="submit" class="btn btn-primary">Sign in</button>
  </form>
{% endblock %}

渲染的HTML:

Custom Crispy Django Form

带有验证状态的渲染的HTML:

Custom Crispy Django Form Validation State


脆皮表单布局帮助器

我们可以使用Crispy表单布局帮助器来实现上述相同的结果。实现是在表单__init__ 方法内完成的:

forms.py

from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column

STATES = (
    ('', 'Choose...'),
    ('MG', 'Minas Gerais'),
    ('SP', 'Sao Paulo'),
    ('RJ', 'Rio de Janeiro')
)

class AddressForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    password = forms.CharField(widget=forms.PasswordInput())
    address_1 = forms.CharField(
        label='Address',
        widget=forms.TextInput(attrs={'placeholder': '1234 Main St'})
    )
    address_2 = forms.CharField(
        widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'})
    )
    city = forms.CharField()
    state = forms.ChoiceField(choices=STATES)
    zip_code = forms.CharField(label='Zip')
    check_me_out = forms.BooleanField(required=False)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('email', css_class='form-group col-md-6 mb-0'),
                Column('password', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'address_1',
            'address_2',
            Row(
                Column('city', css_class='form-group col-md-6 mb-0'),
                Column('state', css_class='form-group col-md-4 mb-0'),
                Column('zip_code', css_class='form-group col-md-2 mb-0'),
                css_class='form-row'
            ),
            'check_me_out',
            Submit('submit', 'Sign in')
        )

模板的实现是非常简单的:

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %}

最终的结果是一样的。

渲染的HTML:

Custom Crispy Django Form

带有验证状态的渲染的HTML:

Custom Crispy Django Form Validation State


自定义脆皮字段

你也可以自定义字段模板,并在你的应用程序中轻松地重复使用。比方说,我们想使用自定义的Bootstrap 4检查框

Bootstrap 4 Custom Checkbox

从官方文档中,输出上述输入的必要HTML:

<div class="custom-control custom-checkbox">
  <input type="checkbox" class="custom-control-input" id="customCheck1">
  <label class="custom-control-label" for="customCheck1">Check this custom checkbox</label>
</div>

使用crispy forms API,我们可以在 "templates "文件夹中为这个自定义字段创建一个新模板。

custom_checkbox.html

{% load crispy_forms_field %}

<div class="form-group">
  <div class="custom-control custom-checkbox">
    {% crispy_field field 'class' 'custom-control-input' %}
    <label class="custom-control-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
  </div>
</div>

现在我们可以创建一个新的crispy字段,可以在我们的forms.py模块中,也可以在一个新的Python模块中,命名为fiiles.py或其他什么。

表单.py

from crispy_forms.layout import Field

class CustomCheckbox(Field):
    template = 'custom_checkbox.html'

我们现在可以在我们的表单定义中使用它。

forms.py

class CustomFieldForm(AddressForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('email', css_class='form-group col-md-6 mb-0'),
                Column('password', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'address_1',
            'address_2',
            Row(
                Column('city', css_class='form-group col-md-6 mb-0'),
                Column('state', css_class='form-group col-md-4 mb-0'),
                Column('zip_code', css_class='form-group col-md-2 mb-0'),
                css_class='form-row'
            ),
            CustomCheckbox('check_me_out'),  # <-- Here
            Submit('submit', 'Sign in')
        )

(PS:AddressForm 是在这里定义的,与前面的例子相同。)

最终的结果:

Bootstrap 4 Custom Checkbox


结论

Django Crispy Forms能做的还有很多。希望本教程能让你对如何使用表单助手和布局类有一些额外的了解。一如既往,官方文档是最好的信息来源。