Ah got it. :) FYI I’ve never used crispy forms as I’ve always rolled my own solution — crispy forms seemed a bit over engineered but I could be wrong.
If you’re looking for a better form layout, you can create a template include (https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#include) and have a form with better fields on it than using the as_p
shortcut. It’s what I do for my startup. For example:
contact.html
<form action="" method="post">
{% csrf_token %}
{% include 'shared/includes/form.html' with form=form %}
<input type="submit" value="Submit" class="btn btn-lg btn-primary"/>
</form>
form.html
{% if form.errors %}
<div class="alert alert-danger">
<p class="text-danger">Please correct the errors below!</p>
</div>
{% endif %}
{% if form.non_field_errors %}
<div class="alert alert-danger">
{% for error in form.non_field_errors %}
<p>{{ error|escape }}</p>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="form-group {% if field.errors %}has-error{% endif %}" id="group_{{ field.name }}">
<label for="id_{{ field.name }}" class="control-label">{{ field.label }}</label>
{{ field }}
{% if field.errors %}
{% for error in field.errors %}
<p class="help-block"><span class="text-danger">{{ error|escape }}</span></p>
{% endfor %}
{% endif %}
{% if field.help_text %}
<p class="help-block">{{ field.help_text }}</p>
{% endif %}
</div>
{% endif %}
{% endfor %}
The above is so it’s in a “bootstrap-y” layout so I can take advantage of Bootstrap’s styling.
Sometimes when I need to completely overhaul a form, I’ll actually just put in the HTML straight. Screenshot from my code: https://www.dropbox.com/s/w48m00f9yi5iv0k/Screenshot%202016-04-02%2013.08.38.png?dl=0
You just need to know what the form fields are being put in by django, so what I usually do is put it in the template as as_p
, then I look at the source, grab the HTML output, and then put that in my templates, adding the Django variables as needed. Example for one field:
<div id="directory_select" class="form-group {% if form.directory.errors %}has-error{% endif %}">
<label class="control-label" for="id_directory">
Vendor category:
</label>
<div class="controls">
{{ form.directory }}
{% if form.directory.errors %}
{% for error in form.directory.errors %}
<span class="help-inline text-danger">{{ error|escape }}</span>
{% endfor %}
{% endif %}
</div>
</div>
Let me know if that helps or if you need more explanation! :) At the very least, don’t forget you could add a unique class to your form and then target the fields within without having to change the HTML too.