【问题标题】:Django form wizard - customized form layout for each stepDjango 表单向导 - 每个步骤的自定义表单布局
【发布时间】:2012-06-25 12:29:44
【问题描述】:

目前我正在尝试使用 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 调用相同的表单布局。因此,我对表单布局进行了双重维护。

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

谢谢!

亲切的问候

【问题讨论】:

  • 如果您在每个步骤中只显示一个表单,那么您只需要 form_else。在这种情况下,您可以显着简化您的模板。不能吗?

标签: django django-forms django-templates django-formwizard


【解决方案1】:

根据 Rohan 的输入并关注post,我找到了一个可行的解决方案:

我的 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 %}

使用它可以在每个步骤中只维护一个表单布局,而不是两个。

【讨论】:

    【解决方案2】:

    您可以为每个步骤创建不同的模板。模板可以根据需要生成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 等。 提示:对于模板中的通用代码(即管理表单字段),创建不同的模板并将它们包含在每一步表单中。

    【讨论】:

    • 您好 Rohan,谢谢您的反馈。事实上,我已经为每个步骤调用了不同的模板。每个都在我的代码中用特定的形式填充block form_ifblock form_else 标记。但是目前我在模板中复制了两次表单(每个块一个),因为我不能在模板中使用相同的块两次 => 给出错误。结果是双重维护。如果您对此有解决方案,我将不胜感激 :) 干杯!
    【解决方案3】:

    在这种情况下,您可以在模板中使用“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 %}
    

    【讨论】:

      【解决方案4】:

      试试看crispy-forms。简而言之,您将在表单上设置一个 helper 实例属性,该属性几乎可以控制您想要通过构建表单来完成的大部分工作,而无需触及模板代码。

      在某些情况下,如果您最终不得不自己手动编写整个标记,那么自定义表单的呈现方式会产生笨拙的模板。在这里,您可以在应用程序的 form_helpers.py 模块中隔离和构建混乱。

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

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

      【讨论】:

      • 嗨 Filip,谢谢您的输入。不完全是我正在寻找的答案,但我肯定会检查这个应用程序。谢谢!
      猜你喜欢
      • 2019-04-18
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      相关资源
      最近更新 更多