Having hard time figuring out crispy


#1

The documentation is not very good and they don’t show visual output of what they are describing.

I would like to see how the complex form here https://getbootstrap.com/docs/4.1/components/forms/#form-grid (the 2nd one under Form Row) would get rendered and instead of a plain checkbox, I want a switch from CoreUI here https://coreui.io/docs/components/switches/

Am I asking too much of crispy?


(cix) #2

Follow this tutorial

I have used it both scenarios, which is get the whole form field also display only the fields you will like to see


#3

I did follow that, but not enough detail for complex forms.


(cix) #4

Can you give a sample of what you would like, either an image or a rough sketch of what the complex form would look like


#5

It’s in the first post. Click the links.


(Vitor Freitas) #6

Hi @dbinott,

I prepared an example for you, I will compile it later on for a blog post, but for now see if it helps.

If I understood correctly, you wanted to render a form like this using crispy forms:

I will give you two options (I like the first one better):

1 Rendering logic in the HTML template

forms.py

from django import forms

STATES = (
    ('', 'Choose...'),
    ('MG', 'Minas Gerais'),
    ('SP', 'Sao Paulo'),
    ('RJ', 'Rio de Janeiro')
)

class AddressForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    password = forms.CharField(widget=forms.PasswordInput())
    address_1 = forms.CharField(label='Address', widget=forms.TextInput(attrs={'placeholder': '1234 Main St'}))
    address_2 = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'}))
    city = forms.CharField()
    state = forms.ChoiceField(choices=STATES)
    zip_code = forms.CharField(label='Zip')
    check_me_out = forms.BooleanField()

form.html

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.email|as_crispy_field }}
      </div>
      <div class="form-group col-md-6 mb-0">
        {{ form.password|as_crispy_field }}
      </div>
    </div>
    {{ form.address_1|as_crispy_field }}
    {{ form.address_2|as_crispy_field }}
    <div class="form-row">
      <div class="form-group col-md-6 mb-0">
        {{ form.city|as_crispy_field }}
      </div>
      <div class="form-group col-md-4 mb-0">
        {{ form.state|as_crispy_field }}
      </div>
      <div class="form-group col-md-2 mb-0">
        {{ form.zip_code|as_crispy_field }}
      </div>
    </div>
    {{ form.check_me_out|as_crispy_field }}
    <button type="submit" class="btn btn-primary">Sign in</button>
  </form>
{% endblock %}

2 Rendering logic in the form definition

from django import forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column


STATES = (
    ('', 'Choose...'),
    ('MG', 'Minas Gerais'),
    ('SP', 'Sao Paulo'),
    ('RJ', 'Rio de Janeiro')
)

class AddressForm(forms.Form):
    email = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    password = forms.CharField(widget=forms.PasswordInput())
    address_1 = forms.CharField(label='Address', widget=forms.TextInput(attrs={'placeholder': '1234 Main St'}))
    address_2 = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Apartment, studio, or floor'}))
    city = forms.CharField()
    state = forms.ChoiceField(choices=STATES)
    zip_code = forms.CharField(label='Zip')
    check_me_out = forms.BooleanField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('email', css_class='form-group col-md-6 mb-0'),
                Column('password', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'address_1',
            'address_2',
            Row(
                Column('city', css_class='form-group col-md-6 mb-0'),
                Column('state', css_class='form-group col-md-4 mb-0'),
                Column('zip_code', css_class='form-group col-md-2 mb-0'),
                css_class='form-row'
            ),
            'check_me_out',
            Submit('submit', 'Sign in')
        )

form.html

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %}


Django Bootstrap Form
#7

Thank you! Very much appreciated!

Why is it you prefer the first one? Seems more typing involved and kind of sidesteps half of what crispy can do.

The 2nd version is what I was looking for. But what about specialty items like converting a checkbox to a switch?


(Vitor Freitas) #8

Actually the crispy forms layouts implementation is pretty nice, my only issue with it is related to the separation of concerns. It sort of mixes the presentation of the information with the data processing. What should be the responsibility of the template/HTML is being handled by the “controller”/Python code in the backend. So in cases where you have a designer/frontend developer working exclusively on the templates and static assets it may not be optimal. Specially because the implementation has some limitations

I mean, the Django form API itself is already doing that (mixing the processing and presentation), rendering the HTML forms using the widgets and everything. But in cases where you have specific needs for the forms, how it needs to be presented, using custom widgets and controls, it may be better to have it in plain HTML

But both ways are fine :grinning:


#9

OK, yes that makes sense.


(Vitor Freitas) #10

I published a new tutorial exploring those cases a little bit:

Code is also available on GitHub:


#11

Wow, that is awesome Vitor. Keep up the up to date articles and I will keep reading.