Django формы и Bootstrap-CSS классы и


Я использую Twitter Bootstrap С Django для визуализации форм.

Bootstrap может форматировать ваши формы довольно красиво - до тех пор, пока у вас есть CSS классы, которые он ожидает включены.

однако, моя проблема заключается в том, что формы, созданные Django's {{ 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>

однако добавление пользовательских меток CSS в каждое поле формы в Django довольно болезненно:

добавить класс в Django label_tag () output

есть ли более умный способ использования {{ form.as_p }}, или итерации по полям, без необходимости вручную указывать вещи, или сделать целую кучу хакерства?

Ура, Виктор

10 59

10 ответов:

Мне нравится использовать "в Django-хрустящие-форм" который является преемником django-uni-form. Это отличный маленький API и имеет большую поддержку Bootstrap.

Я обычно использую фильтры шаблонов для быстрого переноса старого кода и быстрых форм, а также теги шаблонов, когда мне нужно больше контролировать рендеринг.

вот что я придумал:

<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 (оставляя свою версию для 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>

Это 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 %}

чтобы добавить атрибуты CSS в генерируемые Django формы, достаточно использовать следующий код в вашем 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">

Я определенно рекомендую https://github.com/dyve/django-bootstrap-toolkit

например, вы можете создать класс, который определяет атрибуты так, как вы хотите, и просто вызвать его соответствующим образом.

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, и переопределить его as_p метод вывода в формате Bootstrap требуется. Затем измените свои формы, чтобы наследовать от вашего нового класса формы вместо Django.

Bootstrap стили формы с <div>s, а не <p> s. Итак, если вы хотите, чтобы это выглядело красиво, вам нужно пойти bootstrap way 100% IMHO. И вот мой предпочтительный способ сделать это:

использовать 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>

обратите внимание на horizontal в 1) атрибут класса формы 2) макет bootstrap_form и 3) макет кнопок.

вот моя версия с использованием django_tweaks с более привлекательным результатом. Я нахожу render_field легче использовать, чем добавление фильтров. Я также добавил сообщения оповещения в формате bootstrap и отключил проверку навигатора (с помощью 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>