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

Posted

技术标签:

【中文标题】Django 表单向导 - 每个步骤的自定义表单布局【英文标题】:Django form wizard - customized form layout for each step 【发布时间】: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。在这种情况下,您可以显着简化您的模板。不能吗? 【参考方案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,谢谢您的输入。不完全是我正在寻找的答案,但我肯定会检查这个应用程序。谢谢!

以上是关于Django 表单向导 - 每个步骤的自定义表单布局的主要内容,如果未能解决你的问题,请参考以下文章

Django:在表单向导中为步骤动态设置表单集

django 向导,在同一步骤中使用表单和表单集

在 django 表单向导中使用不同的模板

Django 表单向导 - 取决于第一个表单步骤的选择

如何显示作为最终 django 表单向导步骤输入的所有数据的预览?

django 表单向导:全局名称“请求”未在 done() 方法中定义