Domanda

We have a crispy form where we want to be able to render different fields in different parts of our forms HTML template, however we can't find a way of doing this in the Crispy Documentation. Below is some slightly made-up code to illustrate what we are trying to do:

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>

Does anyone know a clean way of achieving this?


The approaches we have looked at so far and had to rule out:

  • We could manually add the fields in our HTML instead of having crispy render them for us. However, this looks to be a no-go because we have a number of choice fields whose options are determined programmatically.
  • We could write a crispy layout which uses an crispy.forms.layout.HTML object to include the HTML which splits up the two different parts of our layout. However, there is a lot of HTML and it would become difficult to maintain if we embedded this directly into python.
  • We could write a Custom Layout Object to do this for us, however we predict this would be quite involved and want to consider this a last resort.
  • We could just not use crispy, and instead look for ways outside of crispy to achieve this, but then we would lose consistency with all the other forms in our application.
È stato utile?

Soluzione

Update: This does not work for forms.ModelForm

Try creating two helpers instead of two layouts then explicitly calling your separate helpers. Doing it this way you will have to manually write <form> tags to enclose both forms in your template but hopefully provides the solution you need.

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')
            )
        )

Then in your template:

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

Altri suggerimenti

create a 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

then in 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})

then in templates you can use in

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>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top