Django Forms 和 Bootstrap - CSS 类和 <divs>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8474409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 02:21:02  来源:igfitidea点击:

Django Forms and Bootstrap - CSS classes and <divs>

cssdjangotwitter-bootstrap

提问by victorhooi

I'm using Twitter Bootstrapwith Django to render forms.

我正在使用Twitter Bootstrap和 Django 来呈现表单。

Bootstrapcan format your forms quite nicely - as long as you have the CSSclasses it expects included.

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

However, my issue is that the forms generated by Django's {{ form.as_p }}don't render well with Bootstrap, as they don't have these classes.

但是,我的问题是 Django 生成的表单{{ form.as_p }}不能用 Bootstrap 很好地呈现,因为它们没有这些类。

For example, the output from Django:

例如,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>

From what I can tell, Bootstrap requires that your forms has a <fieldset class="control-group">, each <label>has class="control-label", and each <input>is wrapped in a <div>:

据我所知,Bootstrap 要求您的表单具有<fieldset class="control-group">,每个<label>都有class="control-label",并且每个<input>都包含在 a 中<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>

However, adding custom CSS labels to every form field in Django is rather painful:

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

Add class to Django label_tag() output

将类添加到 Django label_tag() 输出

Is there a smarter way of either using {{ form.as_p }}, or iterating through the fields, without having to manually specify things, or do a whole bunch of hackery?

是否有更聪明的方法来使用{{ form.as_p }}或遍历字段,而无需手动指定内容,或进行一大堆黑客攻击?

Cheers, Victor

干杯,维克多

采纳答案by erikcw

I like to use "django-crispy-forms"which is the successor to django-uni-form. It's a great little API and has great support for Bootstrap.

我喜欢使用“django-crispy-forms”,它是 django-uni-form 的继承者。这是一个很棒的小 API,并且对 Bootstrap 有很好的支持。

I tend to use the template filters for quickly porting old code and quick forms, and the template tags when I need more control over the rendering.

当我需要更多地控制渲染时,我倾向于使用模板过滤器来快速移植旧代码和快速表单,以及模板标签。

回答by jcmrgo

This is what I came up with:

这就是我想出的:

<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>

回答by Iodnas

When django-crispy-formscannot be used (e.g. when the template treats individually each field of the form), jcmrgo's answer is the only way to go. Based on his answer, here is a solution for Bootstrap 3(leaving his version for Boostrap 2), and with adjustment of field classes inside the template. While field classes are not reachable from within the template with Django's standard library (which leads to that extra forms or template tags in other solutions), here is a solution that sets the right classes to field tags without having to code outside the template:

django-crispy-forms不能使用时(例如,当模板单独处理表单的每个字段时),jcmrgo 的答案是唯一的方法。根据他的回答,这里是Bootstrap 3的解决方案(将他的版本留给 Boostrap 2),并在模板中调整字段类。虽然使用 Django 的标准库无法从模板中访问字段类(这会导致其他解决方案中出现额外的表单或模板标签),但这里有一个解决方案,可以将正确的类设置为字段标签,而无需在模板外编写代码:

{% 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>

This needs django-widget-tweaksinstalled and widget_tweaksadded to INSTALLED_APPS.

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

回答by c4urself

You could do something like this:

你可以这样做:

{% 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 %}

回答by Jaro

In order to add CSS attributes to Django generated forms it's enough to use the following code in your forms.py:

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

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

It will produce the following HTML code:

它将生成以下 HTML 代码:

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

回答by lakesh

For Example, you could created a class which defines the attributes the way you want and just call it accordingly.

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

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)

回答by mehmet

Bootstrap styles forms with <div>s rather than <p>s. So, if you want it to look nice, you need to go bootstrap way 100% IMHO. And here is my preferred way of doing it:

Bootstrap 样式用<div>s 而不是<p>s 形成。所以,如果你想让它看起来不错,你需要 100% 恕我直言。这是我的首选方式:

Use django-bootstrap3app. Example:

使用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>

Notice the horizontalin 1) form class attribute 2) bootstrap_form layout and 3) buttons layout.

注意horizontal1) 表单类属性 2) bootstrap_form 布局和 3) 按钮布局。

回答by Chloé Stévovitch

Here is my version using django_tweaks with a better looking result. I find render_field lighter to use than adding filters. I have also added bootstrap formatted alert messages and turned off navigator validation (with novalidate). I am relatively new to Django so don't hesitate to comment if you find any non-sense

这是我使用 django_tweaks 的版本,效果更好。我发现 render_field 比添加过滤器更容易使用。我还添加了引导程序格式的警报消息并关闭了导航器验证(使用 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>

回答by Chloé Stévovitch

The fastest and easiest way would be to define your own base class that extends the Django Form class, and redefine its as_pmethod to output in the format Bootstrap requires. Then change your forms to inherit from your new Form class instead of Django's.

最快和最简单的方法是定义您自己的扩展 Django Form 类的基类,并重新定义其as_p方法以按 Bootstrap 要求的格式输出。然后更改您的表单以从您的新表单类而不是 Django 类继承。