I'm using Django 1.7 with bootstrap 3 and want to render each form field the same way, best utilizing bootstrap has-error fields:
<div class="form-group {% if form.field.errors %}has-error has-feedback{% endif %}">
<label class="control-label" for="field">{{ form.field.help_text }}</label>
<div class="input-group">
<span class="input-group-addon"><span class="some-icon"></span></span>
{% render_field form.field class+="form-control" placeholder=form.field.label id="end-date" aria-describedby="inputError2Status" %}
</div>
<label class="control-label" for="field">{{ form.field.errors.as_text }}</label>
</div>
As you can see, the moment the number of fields increase it becomes a LOT of work, not only to write it, but also to maintain it and refactoring becomes a hell... not really DRY. For each field I need to change the form.field variables and id="field" and the icon
How would I write a function, templatetag or something else to make django render all the fields in my form this way? Is it even possible to do this? It would be awesome if the Form in django would have a setting to accept an optionalglypycon class which the renderer will use to render the icon.
-- EDIT --
As indicated by @Serafeim django-crispy-forms could be the solution. But how do I use crispy-forms to produce the above html?
-- EDIT 2 --
After reading up on crispy-forms I managed to come up with the following solution: My forms.py file looks like this:
class CreateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CreateForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = 'post'
self.helper.form_action = 'submit'
self.helper.add_input(Submit('submit', 'Submit'))
self.helper.html5_required = True
self.helper.layout = Layout(
PrependedText('fieldA', '<span class="fa fa-calendar"></span>', placeholder="yyyy-mm-dd"),
PrependedText('fieldB', '<span class="fa fa-clock-o"></span>', placeholder="0:00:00 (h:m:s)"),
'fieldC')
fieldA = forms.DateField(required=True)
fieldB = FDurationField(required=True)
fieldC = forms.CharField(widget=forms.Textarea(attrs={'rows':3}), required=False, max_length=128)
class Meta:
model = AModel
exclude = ('fieldD', 'FieldE', 'fieldF', 'fieldG')
and in my template I only have to call {% crispy form %} which is much better than my initial version. However, I still feel like I have to repeat certain steps, like adding the fields to the Layout... Is it possible to reduce the code even further?