Как я могу обойти потребность в классе управления формами Bootstrap 3?

Сегодня вечером я решил впервые опробовать Bootstrap 3. Я заметил, что для того, чтобы получить красивый стиль поля формы по умолчанию, вам нужно добавить класс form-control к каждому вводу, текстовой области, выбору и т. д. Это боль для тех, кто динамически генерирует свои формы (например, используя Django) . Django позволяет вам устанавливать атрибуты полей формы, но для того, чтобы сделать это глобально, потребуется неприятный патч для обезьян или еще очень не СУХОЙ код.

  1. Есть ли способ избежать требования этого класса, сохраняя при этом базовые стили полей формы?
  2. Есть ли быстрый способ (желательно не-JS) решить эту проблему в противном случае?

person orokusaki    schedule 10.08.2013    source источник
comment
Для других пользователей Django, обнаруживших это, мое окончательное решение состояло в том, чтобы просто переопределить Form.__init__ Django, делегировать super, затем повторить self.fields, обновив каждый widget.attrs.get('class', ''), чтобы включить form-control, если виджет был TextInput, Select, или Textarea. Если вы сделаете то же самое, убедитесь, что вы добавили класс form-control, а не просто установили его (чтобы вы не удаляли существующие классы, добавленные в виджет формы.   -  person orokusaki    schedule 06.12.2013
comment
Для пользователей Django: django-widget-tweaks также является приемлемым решением.   -  person Nathan Osman    schedule 28.02.2014


Ответы (3)


Вы действительно должны проверить приложение Django, которое отображает все ваши формы Django как хорошие формы Boostrap, просто используя тег в вашем шаблоне.

Его имя — django-bootstrap3. Вот как вы его используете:

  1. Установите джанго-бутстрап3
  2. Добавьте bootstrap3 к INSTALLED_APPS:

    INSTALLED_APPS = (
        ...
        'bootstrap3',
        ...
    )
    
  3. Обновите свой шаблон:

    1. load bootstrap3
    2. замени {{form.as_p}} на {% bootstrap3_form form %}

до:

<form method="post" class="form-horizontal" action="" >
    <div class="hidden-desktop">
      <button type="submit" class="btn btn-primary"> Save</button>
    </div>
    {% csrf_token %}
    {{ form.as_p }}
    <div class="actions form-actions">
      <button type="submit" class="btn btn-primary"> Save</button>
    </div>
 </form>

после:

{% extends "base.html" %} 
{% load bootstrap3 %}

<form method="post" class="form-horizontal" action="" >
  <div class="hidden-desktop">
    <button type="submit" class="btn btn-primary">{% bootstrap_icon "ok" %} Save</button>
  </div>
  {% csrf_token %}
  {% bootstrap_form form  %}
  <div class="actions form-actions">
    <button type="submit" class="btn btn-primary">{% bootstrap_icon "ok" %} Save</button>
  </div>

Nothing else to do. Nothing to update in you form. No JavaScript hacks.

person ornoone    schedule 29.01.2015
comment
Отлично - я сделал это правильным ответом, хотя я не пробовал приложение. Похоже, что приложение хорошо документировано и поддерживается, и предлагает решение, не требующее настройки. Спасибо. - person orokusaki; 29.01.2015
comment
Требуется небольшое исправление к вашему ответу: 2. замените ваш {{form.as_p}} на {% bootstrap3_form form %} 2. замените ваш {{form.as_p}} на {% bootstrap_form form %} - person Hexatonic; 22.12.2016

Мне было интересно, почему ответ ниже получил отрицательные голоса первым. Я нашел свой ответ о form-group вместо класса form-control. Класс form-control добавляет множество правил CSS.

Вы должны попытаться контролировать вывод своей формы в первую очередь: https://stackoverflow.com/a/8474452/1596547

Если вы не можете, вы можете попробовать то же самое, что и ниже. Примените те же правила к вашим входам вместо form-control, например:

input {
  display: block;
  width: 100%;
  height: 34px;
  padding: 6px 12px;
  font-size: 14px;
  line-height: 1.428571429;
  color: #555555;
  vertical-align: middle;
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border-radius: 4px;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
}

input:focus {
  border-color: #66afe9;
  outline: 0;
  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
}

Меньше

С LESS> 1.4 вы можете использовать :extend(), см.: https://stackoverflow.com/a/15573240/1596547. Вы можете использовать это для вышеперечисленного, добавив правило к своим меньшим файлам:

input {
  &:extend(.form-control all);
}

Также см.: Почему выдает Grunt/Recess ошибку, а Lessc нет при компиляции Bootstrap 3 RC1?

form-group — это контейнер-div вокруг ваших конструкций input/label, он добавляет только margin-bottom: 15px;. Вы можете создавать свои формы без него. По этой причине это не требуется.

С помощью css вы можете сделать некоторые обходные пути. Я не думаю, что вы всегда можете избежать Javascript. Я не знаю HTML-структуру ваших форм Django. Я использовал образец формы из http://getbootstrap.com/css/#forms и удалил form-control контейнеров. Затем я «исправляю» различия. ПРИМЕЧАНИЕ. Я также добавляю тег <br> перед кнопкой отправки.

См.: http://bootply.com/73370

1) form-group добавляет margin-bottom: 15px;, чтобы исправить это, я добавляю это поле к входным тегам:

input {
    margin-bottom: 15px; }

Это работает для флажка (и радио). Bootstrap CSS определяет input[type="radio"], input[type="checkbox"] { line-height: normal; margin: 4px 0 0; }, который имеет приоритет (из-за специфики CSS, см.: http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/ ) CSS для ввода выше.

Таким образом, окончательное правило будет таким:

input, input[type="checkbox"]  {
    margin-bottom: 15px;
}

2) метка чекбокса тоже отличается. ПРИМЕЧАНИЕ. Флажок не имеет окружающего form-control, вместо него используется класс checkbox. Правила css для текста метки: .radio label, .checkbox label { cursor: pointer; display: inline; font-weight: normal; margin-bottom: 0; } В этом случае вы не можете использовать только CSS (метка является родительской для флажка ввода, и в CSS нет родительского селектора, см.: Есть ли родительский селектор CSS?). С помощью jQuery вы можете выбрать метку и добавить класс:

$('input[type="checkbox"]').parent("label").addClass('checkboxlabel');

Теперь добавьте этот класс в свой CSS с теми же правилами, что и .checkbox label:

.checkboxlabel
{
    cursor: pointer;
    display: inline;
    font-weight: normal;
    margin-bottom: 0;
} 

Теперь обе формы выглядят в основном одинаково, я думаю:

формы выглядят одинаково Также читайте: Django Forms и Bootstrap — классы CSS и ‹divs›

person Bass Jobsen    schedule 10.08.2013
comment
Отлично, спасибо! Мне никогда не приходило в голову просто переопределить as_p. Я думаю, это будет намного проще, чем переопределять кучу виджетов, что потребует от меня переопределения formfield_for_dbfield или чего-то еще и т. д. Меня меньше интересовало добавление кучи CSS — хотя мои корни в CSS, Я пытаюсь создать свой сайт с использованием как можно меньшего количества пользовательского CSS, поэтому считаю, что as_p наилучший подход. - person orokusaki; 14.08.2013
comment
@bass-jobsen Возможно, вы не захотите покрывать все входные данные этим стилем, поскольку input[type=button], input[type=radio] и input[type=checkbox] не выигрывают от одного и того же стиля. - person Albert Bori; 04.11.2013
comment
bootstrap также определяет .form-control[disabled],.form-ontrol[readonly],textarea.form-control, .has-warning .form-control:focus и многие другие - person Davi Fiamenghi; 07.01.2014

Одна вещь, которую я сделал, это создал миксин, который добавляет класс form-control к каждому виджету.

class BootStrap3FormControlMixin(object):
    def __init__(self, *args, **kwargs):
        super(BootStrap3FormControlMixin, self).__init__(*args, **kwargs)

        for field in self.fields.values():
            _class = field.widget.attrs.get('class', '')
            field.widget.attrs.update({'class': u'%s %s' % (_class, 'form-control',)})
person emperorcezar    schedule 03.01.2014
comment
Это то, что я в конечном итоге сделал, но см. мой комментарий под исходным вопросом (примечание о добавлении против простой настройки), или вы столкнетесь с проблемами позже, когда захотите добавить еще один класс. Я внес соответствующие изменения в ваш код (также исправил форматирование). - person orokusaki; 05.01.2014