Django Forms and Bootstrap - CSS 类和 <divs>
Posted
技术标签:
【中文标题】Django Forms and Bootstrap - CSS 类和 <divs>【英文标题】:Django Forms and Bootstrap - CSS classes and <divs> 【发布时间】:2012-01-18 10:51:34 【问题描述】:我正在使用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>
但是,在 Django 中为每个表单字段添加自定义 CSS 标签是相当痛苦的:
Add class to Django label_tag() output
有没有更聪明的方法来使用 form.as_p
,或者遍历字段,而无需手动指定事物,或者做一大堆hacky?
干杯, 维克多
【问题讨论】:
您可以查看django-bootstrap-form 和/或django-bootstrap 请告诉我们您最终使用的是哪一个以及为什么! django-bootstrap-form 目前的功能似乎很轻。不过,django-bootstrap 非常有前途,据我所知,它正在为 django 使用正确的方法。这绝对值得贡献。 另见***.com/questions/18158293/… 【参考方案1】:最快和最简单的方法是定义你自己的扩展 Django Form 类的基类,并重新定义其as_p
方法以以 Bootstrap 所需的格式输出。然后将表单更改为从新的 Form 类而不是 Django 类继承。
【讨论】:
【参考方案2】:你可以这样做:
% 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 %
【讨论】:
参见:form.hidden_fields 和 form.visible_fields【参考方案3】:我喜欢使用"django-crispy-forms",它是 django-uni-form 的继承者。这是一个很棒的小 API,并且对 Bootstrap 有很好的支持。
我倾向于使用模板过滤器来快速移植旧代码和快速表单,当我需要更多地控制渲染时使用模板标签。
【讨论】:
我认为这是 2014 年的“正确”答案。 我刚刚检查了 django-crispy-forms github 页面,它看起来很活跃。所以这可能是一个不错的赌注。 (不过,我对此并不了解。) 我不喜欢布局在 django-crispy-forms 中的 python 代码中的事实。 回购在 2017 年看起来仍然很活跃【参考方案4】:我绝对推荐https://github.com/dyve/django-bootstrap-toolkit
【讨论】:
此工具已停用。不再相关。【参考方案5】:例如,您可以创建一个类,该类以您想要的方式定义属性并相应地调用它。
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)
【讨论】:
【参考方案6】:这是我想出的:
<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>
【讨论】:
太棒了!谢谢。我还希望最终能够使标签成为连接到文本框侧面的跨度。我想我需要安装一些其他的包来管理它。 如果您需要跨多个模板使用它,请使用reusable form template。 太棒了,很有用!【参考方案7】:为了给 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">
【讨论】:
【参考方案8】:当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
。
【讨论】:
截至 2015 年,这是最好的答案。特别是如果您赶时间(需要交付)并且没有心情/没有时间学习另一个库,例如脆表格。非常感谢先生! 截至 2016 年,这仍然是无需学习清晰即可轻松集成的最佳答案。 这确实应该是默认答案。 django-crispy-forms 如果您不想模板化您的表单并且有时间使用需要时间学习的大型库,那么 django-crispy-forms 非常好。但是,在原始问题的背景下并以实施时间的名义;这是最好的答案。 要设置占位符 - 如果在表单中定义了一个 - 你可以另外做placeholder=" field.field.widget.attrs.placeholder
。 Django 也可以自己提供所需的id
:id=" field.id_for_label "
和name=" field.html_name
的名称
截至 2018 年,这仍然是最好的答案。我喜欢它在模板中保留演示文稿的内容,而不是清晰的表单,这迫使我将其放入 python 代码中。而且,我喜欢启动和运行相当简单。我唯一的建议是使用“渲染字段”而不是过滤器,下面的另一个答案中有更详细的描述。【参考方案9】:
使用<div>
s 而不是<p>
s 的引导样式表单。所以,如果你想让它看起来不错,你需要 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 »' reset='Reset Form' layout='horizontal' %% endbuttons %
</form>
请注意 1) 表单类属性 2) bootstrap_form 布局和 3) 按钮布局中的 horizontal
。
【讨论】:
我认为这是最优雅的方法,也许最好补充一下,您也可以像这样渲染单个字段:% bootstrap_field form.field_name %
并能够添加表单集等。【参考方案10】:
这是我使用 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>
【讨论】:
【参考方案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 %
【讨论】:
【参考方案12】:在来回搜索文档和 *** 答案之后,这就是我创建的对我有用的内容。
我检查了 django-crispy-forms 的文档,发现它不支持 Bootstrap 5.0 +。
Forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import MyModel
class RegistrationForm(UserCreationForm):
class Meta:
model = MyModel
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
Views.py
from .models import MyModel
from .forms import RegistrationForm
def signup(request):
if request.method == 'POST':
r_form = RegistrationForm(request.POST)
if r_form.is_valid():
r_form.save()
return redirect('home')
else:
r_form = RegistrationForm()
context =
'form': r_form
return render(request, 'myapp/signup.html', context)
Signup.html(for循环方法)
<form action="/signup/" method="post">
% csrf_token %
% for field in form %
<div class="form-floating">
<input
type=" field.field.widget.input_type "
class="form-control"
id=" field.id_for_label "
name="field.name"
required
/>
<label for="field.id_for_label">field.label</label>
</div>
% endfor %
<div class="d-grid gap-2 d-md-block py-2">
<button class="btn btn-primary" type="submit">Sign up</button>
</div>
</form>
Signup.html(手动方法)
<form action="/signup/" method="post">
% csrf_token %
<div class="form-floating my-1">
<input
type="email"
class="form-control"
id="form.email.id_for_label"
name="email"
required
/>
<label for="form.email.id_for_label">Email address</label>
</div>
... next div
我用过这个here bootstrap 例子,你可能需要配置css样式。
参考文献
https://***.com/a/12166096/14682396 https://***.com/a/14647926/14682396 Get the type of field in django template【讨论】:
以上是关于Django Forms and Bootstrap - CSS 类和 <divs>的主要内容,如果未能解决你的问题,请参考以下文章
Django使用haystack借助Whoosh实现全文搜索功能
为啥 Django Crispy Forms 会抛出“模块‘django.forms.forms’没有属性‘BoundField’”
自定义包含 django.forms.CheckboxInput() 的 django.forms.BooleanField() 的样式