Django Forms и Bootstrap - классы CSS и <divs>
Я использую Twitter Bootstrap с Django для рендеринга форм.
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>
Тем не менее, добавление пользовательских меток CSS в каждое поле формы в Django довольно болезненно:
Добавить класс в вывод Django label_tag()
Есть ли более разумный способ использования {{ form.as_p }}
, или итерации по полям, без необходимости вручную что-то указывать, или целой кучей хакерских атак?
Ура,
Виктор
Ответы
Ответ 1
Мне нравится использовать "django-crispy-forms" , который является преемником django-uni-form. Это отличный API и имеет большую поддержку Bootstrap.
Я использую фильтры шаблонов для быстрого переноса старого кода и быстрых форм и тегов шаблонов, когда мне нужно больше контролировать рендеринг.
Ответ 2
Вот что я придумал:
<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>
Ответ 3
Если 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
.
Ответ 4
Вы можете сделать что-то вроде этого:
{% 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 %}
Ответ 5
Чтобы добавить атрибуты CSS в Django сгенерированные формы, достаточно использовать следующий код в ваших формах.
Recepient = forms.ChoiceField(label=u'Recepient', widget=forms.Select(attrs={'id':'combobox'}))
Он выдает следующий код HTML:
<label for="id_Recepient">Recepient</label>
<select id="combobox" name="Recepient">
Ответ 6
Я определенно рекомендую https://github.com/dyve/django-bootstrap-toolkit
Ответ 7
Например, вы можете создать класс, который определяет атрибуты так, как вы хотите, и просто называть его соответствующим образом.
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)
Ответ 8
Формы стиля Bootstrap с <div>
, а не <p>
s. Итак, если вы хотите, чтобы это выглядело красиво, вам нужно перейти на стартовый путь 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 »' reset='Reset Form' layout='horizontal' %}{% endbuttons %}
</form>
Обратите внимание на атрибут класса horizontal
in 1) 2) макет bootstrap_form и 3) макет кнопок.
Ответ 9
Вот моя версия, использующая django_tweaks с лучшим результатом. Я нахожу, что render_field легче использовать, чем добавлять фильтры. Я также добавил бутстрап-форматированные предупреждения и отключил проверку навигатора (с новализацией). Я относительно новичок в 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>
Ответ 10
Самый простой и простой способ - определить собственный базовый класс, который расширяет класс Django Form, и переопределить его метод as_p
для вывода в формате Bootstrap. Затем измените свои формы наследуйте от нового класса Form вместо Django.
Ответ 11
помимо того, что говорили другие друзья, я бы порекомендовал использовать 'django-widget-tweaks'.
ответ будет что-то вроде этого:
{% for field in form %}
<label for="{{ field.label }}">{{ field.label }}</label>
{{ field|add_class:"form-control" }}
<span class="error-block">{{ field.errors }}</span>
{% endfor %}