Django Crispy 表单拆分字段布局

Posted

技术标签:

【中文标题】Django Crispy 表单拆分字段布局【英文标题】:Django Crispy Form Split Field Layouts 【发布时间】:2013-07-21 01:30:08 【问题描述】:

我们有一个清晰的表单,我们希望能够在表单html 模板的不同部分呈现不同的字段,但是我们在Crispy Documentation 中找不到这样做的方法。下面是一些稍微编造的代码来说明我们正在尝试做的事情:

forms.py

helper = FormHelper()
helper.layout_1 = Layout(
    Div(
        Field('field_1a'),
        Field('field_1b')
    )
)
helper.layout_2 = Layout(
    Div(
        Field('field_2a'),
        Field('field_2b')
    )
)

template.html

<body>
    % crispy form layout_1 %
    <!-- A big bunch of other html -->
    % crispy form layout_2 %
</body>

有人知道实现这一目标的干净方法吗?


到目前为止我们已经研究过并且不得不排除的方法:

我们可以在 HTML 中手动添加字段,而不是让脆皮为我们呈现它们。但是,这似乎是不可能的,因为我们有许多 choice 字段,其选项是通过编程方式确定的。 我们可以编写一个清晰的布局,它使用一个crispy.forms.layout.HTML 对象来包含分割我们布局的两个不同部分的HTML。但是,有很多 HTML,如果我们将其直接嵌入到 python 中,将变得难以维护。 我们可以写一个Custom Layout Object 来为我们做这件事,但我们预计这会涉及很多,并希望考虑这是最后的手段。 我们不能不使用脆皮,而是寻找脆皮之外的方法来实现这一点,但这样我们就会失去与应用程序中所有其他形式的一致性。

【问题讨论】:

这是您正在使用的ModelForm 吗? 不,这只是香草django.forms.Form 那么,crispy 是否将所有字段渲染两次,而不仅仅是您在每个布局中指定的字段?我没有看到您当前的解决方案有什么问题。 我们在布局的不同部分渲染不同的字段。上面的代码实际上并没有工作——这更多是为了说明我们想要尝试和做的事情(如果不够清楚,请道歉) 【参考方案1】:

更新:这不适用于forms.ModelForm

尝试创建两个助手而不是两个布局,然后显式调用您的单独助手。这样做,您将不得不手动编写&lt;form&gt; 标签以将这两个表单包含在您的模板中,但希望能提供您需要的解决方案。

forms.py

class Form(forms.Form):
    field_1a = forms.CharField()
    field_1b = forms.CharField()
    field_2a = forms.CharField()
    field_2b = forms.CharField()

    def __init__(self, *args, **kwargs):
        super(Form, self).__init__(*args, **kwargs)
        self.helper1 = FormHelper()
        self.helper1.form_tag = False
        self.helper1.layout = Layout(
            Div(
                Field('field_1a'),
                Field('field_1b')
            )
        )

        self.helper2 = FormHelper()
        self.helper2.form_tag = False
        self.helper2.disable_csrf = True
        self.helper2.layout = Layout(
            Div(
                Field('field_2a'),
                Field('field_2b')
            )
        )

然后在你的模板中:

<body>
<form>
% crispy form form.helper1 %
<!-- A big bunch of other html -->
% crispy form form.helper2 %
</form>
</body>

【讨论】:

@scott 我正在尝试这个,但问题是第二个助手(再次)渲染了第一个助手中的字段。有什么线索吗? 这在使用 ModelForm 时不起作用。每个帮助器都会输出每个表单字段,无论布局中有哪些字段。 @EronVillarreal 对于 ModelForms,您可以在 __init__ 块的末尾添加一个 if hasattr(self.Meta, 'fields'): delattr(self.Meta, 'fields') 来解决这个问题【参考方案2】:

创建一个form.py

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Field,Layout, ButtonHolder, Submit
class layout1Form(forms.Form):    
    def __init__(self, *args, **kwargs):
        super(layout1Form, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
           Field('answer',css_class="field span8"),
           ButtonHolder(
              Submit('submit', 'Submit', css_class='btn-primary pull-right')
            )
          )
        self.helper.form_tag = False

class layout2Form(forms.Form):    
    def __init__(self, *args, **kwargs):
        super(layout1Form, self).__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
           Field('answer',css_class="field span8"),
           ButtonHolder(
              Submit('submit', 'Submit', css_class='btn-primary pull-right')
            )
          )
        self.helper.form_tag = False

然后在views.py中

views.py

from ...forms import layout1Form,layout2Form
def layouttest(request):
    form = layout1Form(request.POST)
    form1=layout2Form(request.POST)
    return render(request,'test.html','frm1':form,'frm2':form1)

然后你可以在模板中使用

test.html

<form id="signup" class="form-horizontal" method="post" action="">
% crispy frm1 %
   ""the big html""
% crispy frm2 %
<button type="submit" class="btn btn-success">Submit</button>   
</form>

【讨论】:

感谢@suhail 的建议,我们曾考虑使用 HTML 元素,但是我们在布局的不同部分之间有很多 HTML,并且希望避免在 python 代码中嵌入如此多的 HTML (因为维护 HTML 会更加困难)。 @robjohncox 可能你可以使用像self.helper['&lt;fieldname&gt;'].wrap(Field, template="&lt;template path&gt;")这样的模板 很有趣,看起来它可以工作。我们可能会走这条路——等着看人们可能有什么其他建议。 @robjohncox 我已经以其他方式将我的答案更新为 .实际上我正在使用crispyforms。这些取自我的工作项目 啊,所以它可以分成两种形式,这是有道理的。对于我们的用例,另一种方法(来自@scottwoodall)更适合一些,但仍然是一个简洁的解决方案,因此为您 +1。

以上是关于Django Crispy 表单拆分字段布局的主要内容,如果未能解决你的问题,请参考以下文章

Django Crispy 表单根据需要设置模型字段

Django:模板中的 Crispy 表单验证错误

替代 django-crispy-forms

使用 Django 模型表单 + 表单向导 + Crispy - 不进行第二步

Django Crispy Forms 重新排列布局并保留 Bootstrap 内联格式?

Django Crispy 表单提交按钮