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
尝试创建两个助手而不是两个布局,然后显式调用您的单独助手。这样做,您将不得不手动编写<form>
标签以将这两个表单包含在您的模板中,但希望能提供您需要的解决方案。
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['<fieldname>'].wrap(Field, template="<template path>")
这样的模板
很有趣,看起来它可以工作。我们可能会走这条路——等着看人们可能有什么其他建议。
@robjohncox 我已经以其他方式将我的答案更新为 .实际上我正在使用crispyforms。这些取自我的工作项目
啊,所以它可以分成两种形式,这是有道理的。对于我们的用例,另一种方法(来自@scottwoodall)更适合一些,但仍然是一个简洁的解决方案,因此为您 +1。以上是关于Django Crispy 表单拆分字段布局的主要内容,如果未能解决你的问题,请参考以下文章
使用 Django 模型表单 + 表单向导 + Crispy - 不进行第二步