16

I'm using django-crispy-forms with Twitter Bootstrap , and I'm having some issues with customizing my forms into multiple rows and columns. One example problem is that nothing happens when I try to split the form into two columns:

class SomeForm(ModelForm):

    helper = FormHelper()
    helper.layout = Layout(
        Column('field1', 'field3'),
        Column('field2', 'field4'),
        )
    )

    class Meta:
        model = Model

Looking at the html output, I see that there is the <div class="formColumn">, but the form is displayed in one single column. Maybe is this an css issue? I am using Bootstrap 2.1.

martinpaulucci
  • 2,322
  • 5
  • 24
  • 28

4 Answers4

35

Thanks maraujo.

I've achieved this using the div tag and the bootstrap docs: http://twitter.github.com/bootstrap/scaffolding.html

class SomeForm(ModelForm):

    helper = FormHelper()
    helper.layout = Layout(
        Div(
            Div('field1', css_class='span6'),
            Div('field3', css_class='span6'),  
        css_class='row-fluid'), 
    )

    class Meta:
        model = Model

For bootstrap3 replace span6 with col-xs-6 http://getbootstrap.com/css/#grid

madzohan
  • 11,488
  • 9
  • 40
  • 67
martinpaulucci
  • 2,322
  • 5
  • 24
  • 28
16

Small 2018 update on the answer by martinpaulucci:

For Bootstrap 4 and latest django-crispy-forms 1.7.2 use:

class SomeForm(ModelForm):

    helper = FormHelper()
    helper.layout = Layout(
        Div(
            Field('field1', wrapper_class='col-md-3'),
            Field('field3', wrapper_class='col-md-9'),  
        css_class='form-row') 
    )

    class Meta:
        model = Model

The use of the Field tag in stead of the Div tag avoids another unnecessary wrapper div. To improve on that you can replace crispy-forms Row with your own if you're going to use more than one row:

class Row(Div):
    css_class = "form-row"

then use:

class SomeForm(ModelForm):

    helper = FormHelper()
    helper.layout = Layout(
        Row(
            Field('field1', wrapper_class='col-md-3'),
            Field('field3', wrapper_class='col-md-9')  
        ) 
    )

    class Meta:
        model = Model
Pepijn
  • 383
  • 2
  • 13
3

Had issue with Django3 + ModelForm displaying multiple fields on the same row like this

def __init__(self, *args, **kwargs):
    super(SupplierDetailForm, self).__init__(*args, **kwargs)

    self.helper = FormHelper(self)
    self.helper.layout = Layout(
        Row(
            Column('nom', css_class='form-group col-2 mb-0'),
            Column('email', css_class='form-group col-4 mb-0'),
        )
    )

I noticed that Crispy "row" class is in fact a "form-row" class that doesn't match with Bootstrap 4 classes.

Pepijn's tip did the job. Thanks

Abpostman1
  • 158
  • 1
  • 8
  • Please don't add "thank you" as an answer. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation), you will be able to [vote up questions and answers](https://stackoverflow.com/help/privileges/vote-up) that you found helpful. - [From Review](/review/late-answers/30069869) – My Stack Overfloweth Oct 13 '21 at 16:36
  • This should be the accepted answer. Awesome, thanks. – Jhnsbrst Jan 08 '22 at 12:16
3

June 2022 Update on the answer by martinpaulucci and Pepijn:
For Bootstrap 5 and django-crispy-forms 1.14.0, css_class = "form-row" no longer works. Instead use 'row':

class Row(Div):
    css_class = 'row'

Here's an example implementation using the Row class defined by Pepijn above (forms.py):

class Row(Div):
    css_class = 'row g-3'

class BlogUserCreationForm(UserCreationForm):
    """
    Create a custom user creation form using the custom BlogUser user model.
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Field('username', wrapper_class='form-group col-md-6 mb-0'),
                Field('email', wrapper_class='form-group col-md-6 mb-0'),
            ),
            'password1',
            'password2',
            Row(
                Field('first_name', wrapper_class='form-group col-md-4 mb-0'),
                Field('last_name', wrapper_class='form-group col-md-4 mb-0'),
                Field('date_born', wrapper_class='form-group col-md-4 mb-0'),
            ),
            'short_bio',
            Submit('submit', 'Submit')
        )

    class Meta:
        model = BlogUser
        fields = ("username", 'email', 'password1', 'password2', 'first_name', 'last_name', 'date_born', 'short_bio')

(I added 'g-3' to my css_class in the implementation to add gutters between the rows).

In case anyone is curious, in my settings.py the crispy_template_pack is still defined as bootstrap4 as per the docs; however, bootstrap5 still seems to work with django-crispy-forms so far as I've found.

CRISPY_TEMPLATE_PACK = 'bootstrap4'