Django 表单向导 - 为每个步骤自定义表单布局



目前我正在试验django表单向导。基本设置现在可以工作了,我可以为每个显示可变文本的步骤调用不同的模板。

现在,我想更进一步,为每个步骤创建自定义表单布局。Django 的文档展示了一种显示表单的通用方式,始终采用垂直对齐方式。

在我的实验中,我有两个步骤:

  • 步骤1:电子邮件和密码(只有两个需要垂直对齐的字段)
  • 第 2 步:个人数据:地址、职业、...

因此,对于第 2 步,我想使用完全不同的表单布局,然后是第 1 步:使用字段集、字段的水平对齐(例如地址:街道和号码)、......

从 django 文档开始,我想以下内容可以工作(尚未测试):

{% block content %}
# block step: variable text for each step
{% block step %}{% endblock %}
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
    {{ wizard.form.management_form }}
    {% for form in wizard.form.forms %}
        # block form_if: shows a complete customized form layout for each step
        {% block form_if %}{% endblock %}
    {% endfor %}
{% else %}
    # block form_else: shows a complete customized form layout for each step
    {% block form_else %}{% endblock %}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans    "first step" %}</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
{% endblock %}

但是我在这里遇到的问题是我有两个blocksform_ifform_else调用相同的表单布局。因此,我对表单布局进行了双重维护。

有没有更好的方法来实现我想要实现的目标?

谢谢!

亲切问候

根据 Rohan 的输入和以下帖子,我找到了一个可行的解决方案:

我的base_wizard模板如下所示:

<form enctype="multipart/form-data" action="" method="post">{% csrf_token %}
    <table>
        {{ wizard.management_form }}
        {% if wizard.form.forms %}
            {{ wizard.form.management_form }}
            {% for form in wizard.form.forms %}
                <!-- block below accesses a customized form layout for each step -->
                {% block form_if %}{% endblock %}
            {% endfor %}
        {% else %}
            <!-- block below accesses a customized form layout for each step -->
            <!-- using the with statement makes it possible to use the same layout used in the form_if block -->
            {% with form=wizard.form %}
            {% block form_else %}{% endblock %}
            {% endwith %}
        {% endif %}
    </table>
    {% if wizard.steps.prev %}
    <button name="wizard_goto_step" value="{{ wizard.steps.first }}" class="button">{% trans "first step" %}</button>
    <button name="wizard_goto_step" value="{{ wizard.steps.prev }}" class="button">{% trans "prev step" %}</button>
    {% endif %}
    <div>
        <input type="submit" value="{% trans "submit" %}" class="button"/>
    </div>  
</form>

在每个步骤的模板中,我使用以下代码:

{% extends "base_wizard.html" %}
{% block form_if %}{% block form_else %}
    <fieldset>
        <legend>Title</legend>
        <div>
            <label>{{ form.field.label }}:<p class="note">{{ form.field.help_text }}</p></label> {{ form.field }}
            <p class="error">
                {% if form.field.errors %}
                    {% for error in form.field.errors %}
                        {{ error }}
                    {% endfor %}
                {% endif %}
            </p>
        </div>
    </fieldset>
{% endblock %}{% endblock %}

使用此功能,每个步骤只需维护一个表单布局,而不是两个。

您可以为每个步骤创建不同的模板。模板可以根据需要生成 html。

要告诉 django 使用不同的表单模板作为步骤,您可以按照这个...

class TestFormWizard(SessionWizardView):
    def get_template_names(self):
        if self.steps.current == 1:
            return 'step1_form.html'
        if self.steps.current == 2:
            return 'step2_form.html'
        return 'wz_form.html'

您可以根据需要定义step1_form.html、step2_form.html等。提示:对于模板(即管理表单字段)中的常见代码,请创建不同的模板并将其包含在每步骤表单中。

在这种情况下,

您可以在模板中使用"with"语句。像这样:在你的block_if和block_else将形式称为myform。

{{ wizard.management_form }}
{% if wizard.form.forms %}
    {{ wizard.form.management_form }}
    {% for form in wizard.form.forms %}
        # block form_if: shows a complete customized form layout for each step
        {% with myform=form %}
        {% block form_if %}{% endblock %}
        {%e endwith %}
    {% endfor %}
{% else %}
    # block form_else: shows a complete customized form layout for each step
    {% with myform=form %}    
    {% block form_else %}{% endblock %}
    {% endwith %}
{% endif %}

试着给脆皮看一看。简而言之,您将在表单上设置一个helper实例属性,该属性几乎可以控制您希望在不接触模板代码的情况下通过构建表单完成的大部分工作。

在某些情况下,如果您最终不得不自己编写整个标记,则自定义表单的演示文稿会使模板变得笨拙。在这里,您可以在应用程序的form_helpers.py模块中隔离和构建混乱。

如果您可以使用crispy-forms在创建表单布局方面提供的内容,您将看到定义表单帮助程序的布局所需的大约 10 行代码使您摆脱了数十行模板代码,否则您必须维护。

在这种情况下,您最终会得到的是多个表单、每个特定表单的表单帮助程序实例以及一个仅调用 crispy-form 标记的模板来呈现向导为每个步骤提供的表单。

最新更新