2013-03-01 68 views
11

我有一个django Formset,我想在另一个表格的中间布局。我使用django-crispy-forms设置在布局父窗体的__init__django脆皮表格:在表格中嵌套一个表格

from crispy_forms.helper import FormHelper 
from crispy_forms.layout import Submit, Layout, Field, Div 
def __init__(self, *args, **kwargs): 
    self.helper = FormHelper() 
    self.helper.layout = Layout(
     Div(
      Div(Field('foo'), css_class='span3'), 
      Div(Field('bar'), css_class='span4'), 
      css_class='row' 
      ), 
     Field('baz', css_class='span1'), 
      ... 
      ) 
    self.helper.add_input(Submit('submit', 'Submit', css_class='btn btn-primary offset4')) 

我的模板,只是呈现使用{% crispy %}标签形式。

我想知道我应该如何合并formset。我应该在上面的init函数中实例化它吗?我该如何参考它?

在网上有一个表单和formset组合的other examples,它们之间有一个呈现在另一个之后,但我想知道我是否可以更好地控制它们与松脆布局的搭配。

回答

16

我解决了这个不修改脆皮形式,通过创建使一个formset新的字段类型:

from crispy_forms.layout import LayoutObject, TEMPLATE_PACK 

class Formset(LayoutObject): 
    """ 
    Layout object. It renders an entire formset, as though it were a Field. 

    Example:: 

    Formset("attached_files_formset") 
    """ 

    template = "%s/formset.html" % TEMPLATE_PACK 

    def __init__(self, formset_name_in_context, template=None): 
     self.formset_name_in_context = formset_name_in_context 

     # crispy_forms/layout.py:302 requires us to have a fields property 
     self.fields = [] 

     # Overrides class variable with an instance level variable 
     if template: 
      self.template = template 

    def render(self, form, form_style, context, template_pack=TEMPLATE_PACK): 
     formset = context[self.formset_name_in_context] 
     return render_to_string(self.template, Context({'wrapper': self, 
      'formset': formset})) 

它需要一个模板来渲染表单集,这让你在它究竟是如何呈现的控制:

{% load crispy_forms_tags %} 

<div class="formset"> 
    {% crispy formset %} 
    <input type="button" name="add" value="Add another" /> 
</div> 

你可以用它在你的布局中嵌入一个formset就像任何其他脆皮布局元素:

self.helper.layout = Layout(
    MultiField(
     "Education", 
     Formset('education'), 
    ), 
+2

一个轻微的修改,我建议是一个可选的参数添加到该formset LayoutObject为'formset_helper'。这也是一样的。这样你也可以传入自定义助手。 – Alejandro 2015-07-10 18:29:39

+1

这些代码放在哪个文件中?我在哪里放置formset.html?什么是Formset('教育');它从哪里来? – 2017-02-13 12:36:33

3

目前不支持松脆形式。您唯一的选择是使用|as_crispy_field过滤器(尚未记录,对不起)。

我已经开始这个功能的开发{% crispy %}标签和一个特性分支,它在这里的所有解释:https://github.com/maraujop/django-crispy-forms/issues/144

我在寻找反馈,所以如果你仍然有兴趣,随意张贴。

2

稍早修改qris

此更新(如Alejandro建议)将允许我们自定义表单集布局对象使用FormHelper对象来控制表单集的字段如何呈现。

from crispy_forms.layout import LayoutObject 

from django.template.loader import render_to_string 


class Formset(LayoutObject): 
    """ 
    Renders an entire formset, as though it were a Field. 
    Accepts the names (as a string) of formset and helper as they 
    are defined in the context 

    Examples: 
     Formset('contact_formset') 
     Formset('contact_formset', 'contact_formset_helper') 
    """ 

    template = "forms/formset.html" 

    def __init__(self, formset_context_name, helper_context_name=None, 
       template=None, label=None): 

     self.formset_context_name = formset_context_name 
     self.helper_context_name = helper_context_name 

     # crispy_forms/layout.py:302 requires us to have a fields property 
     self.fields = [] 

     # Overrides class variable with an instance level variable 
     if template: 
      self.template = template 

    def render(self, form, form_style, context, **kwargs): 
     formset = context.get(self.formset_context_name) 
     helper = context.get(self.helper_context_name) 
     # closes form prematurely if this isn't explicitly stated 
     if helper: 
      helper.form_tag = False 

     context.update({'formset': formset, 'helper': helper}) 
     return render_to_string(self.template, context.flatten()) 

模板(用于渲染表单集):

{% load crispy_forms_tags %} 

<div class="formset"> 
    {% if helper %} 
    {% crispy formset helper %} 
    {% else %} 
    {{ formset|crispy }} 
    {% endif %} 
</div> 

现在,它可以在任何布局中使用,就像任何其他形式的酥脆布局对象。

self.helper.layout = Layout(
    Div(
     Field('my_field'), 
     Formset('my_formset'), 
     Button('Add New', 'add-extra-formset-fields'), 
    ), 
) 

# or with a helper 
self.helper.layout = Layout(
    Div(
     Field('my_field'), 
     Formset('my_formset', 'my_formset_helper'), 
     Button('Add New', 'add-extra-formset-fields'), 
    ), 
) 
0

上述溶液表单集(LayoutObject)基础上,你将结合Django的动态表单集中&香脆。 在我的订单页面上,我有:

  • 订单的部分第1个部分
  • 为了与在线表单集动态添加表格
  • 订单的部分部N

现在很简单明了,ModelForms是:

class OrderTestForm(forms.ModelForm): 
def __init__(self, *args, **kwargs): 
    super(OrderTestForm, self).__init__(*args, **kwargs) 
    self.helper = FormHelper(self) 
    self.helper.form_tag = True 
    self.helper.html5_required = True 
    self.helper.form_action = 'test_main' 
    self.helper.layout = Layout(
     'product_norms', #section 1 
     'reference_other', #section 1 
     # rest of the section 1 fields 
     Formset('samples', 'helper'), # inline dynamic forms 
     'checkbox_is_required' # start of section N 
     # other order sections fields 
    ) 
    self.helper.add_input(Submit("submit", "Save order")) 

Formset帮助程序布局:

class SamplesFormSetHelper(FormHelper): 
def __init__(self, *args, **kwargs): 
    super(SamplesFormSetHelper, self).__init__(*args, **kwargs) 
    self.form_method = 'post' 
    self.html5_required = True 
    self.layout = Layout(
     Fieldset('', 
     'description', 
     'product', # foreign key 
     'DELETE', # delete django-dynamic-formset 
     css_class="formset_row"), # add-rows 
    ) 
    self.form_tag = False 
    self.render_required_fields = False 

添加/删除内联,使用formset操作保存订单按预期工作。