Django Forms和Bootstrap – CSS类和<divs>

我用Django的Twitter Bootstrap来渲染表单。

Bootstrap可以很好地格式化你的表单 – 只要你有它期望包含的CSS类。

不过,我的问题是由Django {{ form.as_p }}生成的表单不能很好地与Bootstrap一起呈现,因为它们没有这些类。 例如,Django的输出:

 <form class="horizontal-form" action="/contact/" method="post"> <div style='display:none' <input type='hidden' name='csrfmiddlewaretoken' value='26c39ab41e38cf6061367750ea8c2ea8'/> </div> <p><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" value="FOOBAR" maxlength="20" /></p> <p><label for="id_directory">Directory:</label> <input id="id_directory" type="text" name="directory" value="FOOBAR" maxlength="60" /></p> <p><label for="id_comment">Comment:</label> <textarea id="id_comment" rows="10" cols="40" name="comment">Lorem ipsum dolor sic amet.</textarea></p> <p><label for="id_server">Server:</label> <select name="server" id="id_server"> <option value="">---------</option> <option value="1" selected="selected">sydeqexcd01.au.db.com</option> <option value="2">server1</option> <option value="3">server2</option> <option value="4">server3</option> </select></p> <input type="submit" value="Submit" /> </form> 

根据我所知,Bootstrap要求你的表单有一个<fieldset class="control-group"> ,每个<label>具有class="control-label" ,每个<input>被封装在一个<div>

 <fieldset class="control-group"> <label class="control-label" for="input01">Text input</label> <div class="controls"> <input type="text" class="xlarge" name="input01"> <p class="help-text">Help text here. Be sure to fill this out like so, or else!</p> </div> </fieldset> 

然而,在Django的每个表单字段中添加自定义的CSS标签是相当痛苦的:

将类添加到Django的label_tag()输出

使用{{ form.as_p }}或遍历字段,而不必手动指定事物,或者做一大堆hackery是否有一个更明智的方法?

干杯,维克多

我喜欢使用django-uni-form的inheritance者“django-crispy-forms” 。 这是一个很棒的API,对Bootstrap有很大的支持。

我倾向于使用模板filter快速移植旧代码和快速表单,以及在需要更多控制渲染时使用模板标记。

这就是我想到的:

 <form class="form-horizontal" method="post">{% csrf_token %} <fieldset> <legend>{{ title }}</legend> {% for field in form %} {% if field.errors %} <div class="control-group error"> <label class="control-label">{{ field.label }}</label> <div class="controls">{{ field }} <span class="help-inline"> {% for error in field.errors %}{{ error }}{% endfor %} </span> </div> </div> {% else %} <div class="control-group"> <label class="control-label">{{ field.label }}</label> <div class="controls">{{ field }} {% if field.help_text %} <p class="help-inline"><small>{{ field.help_text }}</small></p> {% endif %} </div> </div> {% endif %} {% endfor %} </fieldset> <div class="form-actions"> <button type="submit" class="btn btn-primary" >Submit</button> </div> </form> 

当不能使用django-crispy-forms (例如,当模板单独处理表单的每个字段时),jcmrgo的答案是唯一的方法。 基于他的回答,这里是一个Bootstrap 3的解决scheme(离开他的版本Boostrap 2),并调整模板内的字段类 。 尽pipeDjango的标准库(在其他解决scheme中会导致额外的表单或模板标签)无法从字段类中获得字段类,但是这种解决scheme将正确的类设置为字段标签,而无需在模板之外进行编码:

 {% load i18n widget_tweaks %} <form class="form-horizontal" role="form" action="." method="post"> {% csrf_token %} {% for field in form %} {% if field.errors %} <div class="form-group has-error"> <label class="col-sm-2 control-label" for="id_{{ field.name }}">{{ field.label }}</label> <div class="col-sm-10"> {{ field|attr:"class:form-control" }} <span class="help-block"> {% for error in field.errors %}{{ error }}{% endfor %} </span> </div> </div> {% else %} <div class="form-group"> <label class="col-sm-2 control-label" for="id_{{ field.name }}">{{ field.label }}</label> <div class="col-sm-10"> {{ field|attr:"class:form-control" }} {% if field.help_text %} <p class="help-block"><small>{{ field.help_text }}</small></p> {% endif %} </div> </div> {% endif %} {% endfor %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-primary">{% trans "Submit" %}</button> </div> </div> </form> 

这需要安装django-widget-tweaks并将widget_tweaks添加到INSTALLED_APPS

你可以做这样的事情:

 {% for field in form %} <fieldset class="control-group"> <label class="control-label" for="id_{{ field.name }}">{{ field.label }}</label> <div class="controls"> {{ field }} <p class="help-text">{{ field.help_text }} </p> </div> </fieldset> {% endfor %} 

为了给Django生成的表单添加CSS属性,在forms.py中使用下面的代码就足够了:

 Recepient = forms.ChoiceField(label=u'Recepient', widget=forms.Select(attrs={'id':'combobox'})) 

它会产生下面的HTML代码:

 <label for="id_Recepient">Recepient</label> <select id="combobox" name="Recepient"> 

例如,您可以创build一个类,以您想要的方式定义属性,并相应地调用它。

 class ContactForm(ModelForm): class Meta: model = Contact created = MyDatePicker() class Uniform(forms): def __init__(self, *args, **kwargs): attrs = kwargs.pop("attrs",{}) attrs["class"] = "span3" kwargs["attrs"] = attrs super(Uniform, self).__init__(*args, **kwargs) class MyDatePicker(Uniform,forms.DateInput) def __init__(self, *args, **kwargs): attrs = kwargs.pop("attrs",{}) attrs["class"] = "datepick" attrs["id"] =kwargs.get('datetag', '') kwargs["attrs"] = attrs super(MyDatePicker, self).__init__(*args, **kwargs) 

最快和最简单的方法是定义你自己的扩展Django Form类的基类,并重新定义它的as_p方法以Bootstrap需要的格式输出。 然后改变你的表单从你的新的Form类inheritance,而不是Django的。

Bootstrap样式使用<div> s而不是<p> 。 所以,如果你想要它看起来不错,你需要去引导方式100%恕我直言。 这是我喜欢的方式:

使用django-bootstrap3应用程序。 例:

 {% load bootstrap3 %} <form class="signup form-horizontal" id="signup_form" method="post" action="{% url 'account_signup' %}"> {% csrf_token %} {% bootstrap_form form layout="horizontal" %} {% buttons submit='Sign Up &raquo;' reset='Reset Form' layout='horizontal' %}{% endbuttons %} </form> 

注意1)表单类属性2)bootstrap_form布局和3)button布局中的水平。

这是我的版本使用django_tweaks更好看的结果。 我发现使用render_field比添加filter更轻。 我还添加了引导格式的警报消息,并closures导航器validation(与novalidate)。 我对Django来说是比较新的,所以如果你觉得没有任何意义的话,请不要犹豫

 <form class="large" method="post" action="/suscript/" novalidate> {% csrf_token %} <fieldset> <legend>{{ title }}</legend> {% for field in form %} <div class="control-group {%if field.errors %}error{%endif%}"> <div class="input-group controls"> <label class="input-group-addon control-label" id="{{field.label|safe}}">{{ field.label }}</label> {% render_field field type="text" class="form-control" placeholder="" aria-describedby="field.label|safe" %} </div> {% for error in field.errors %} <div class="alert alert-danger"> <strong>{{ error|escape }}</strong> </div> {% endfor %} {% if field.help_text %} <p class="help-inline">{{ field.help_text|safe }}</p> {% endif %} </div> {% endfor %} </fieldset> <div class="form-actions"> <button type="submit" class="btn btn-primary" >Submit</button> </div> </form>