Skip to content

Commit 0e4f097

Browse files
committed
Merge branch 'release/4.3.0'
2 parents 5fc3078 + c805c65 commit 0e4f097

File tree

12 files changed

+62
-14
lines changed

12 files changed

+62
-14
lines changed

HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
History
44
-------
55

6+
4.3.0 (2014-04-25)
7+
++++++++++++++++++
8+
9+
* added `required_css_class` and `error_css_class` as optional settings (global) and parameters (form and field rendering)
10+
11+
612
4.2.0 (2014-04-06)
713
++++++++++++++++++
814

bootstrap3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# -*- coding: utf-8 -*-
22

3-
__version__ = '4.2.0'
3+
__version__ = '4.3.0'

bootstrap3/bootstrap.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
'horizontal_label_class': 'col-md-2',
1717
'horizontal_field_class': 'col-md-4',
1818
'set_required': True,
19+
'form_required_class': '',
20+
'form_error_class': '',
1921
'form_renderers': {
2022
'default': 'bootstrap3.renderers.FormRenderer',
2123
},

bootstrap3/forms.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,23 @@ def render_label(content, label_for=None, label_class=None, label_title=''):
5555
return render_tag('label', attrs=attrs, content=content)
5656

5757

58-
def render_button(content, button_type=None, icon=None):
58+
def render_button(content, button_type=None, icon=None, button_class=''):
5959
"""
6060
Render a button with content
6161
"""
62-
attrs = {'class': 'btn'}
62+
attrs = {}
63+
attrs['class'] = add_css_class('btn', button_class)
6364
if button_type:
6465
if button_type == 'submit':
65-
attrs['class'] += ' btn-primary'
66+
attrs['class'] = add_css_class(attrs['class'], 'btn-primary')
6667
elif button_type != 'reset' and button_type != 'button':
6768
raise BootstrapError('Parameter "button_type" should be "submit", "reset", "button" or empty.')
6869
attrs['type'] = button_type
6970
icon_content = render_icon(icon) if icon else ''
7071
return render_tag('button', attrs=attrs, content=text_concat(icon_content, content, separator=' '))
7172

7273

73-
def render_field_and_label(field, label, field_class='', label_class='', layout='', **kwargs):
74+
def render_field_and_label(field, label, field_class='', label_for=None, label_class='', layout='', **kwargs):
7475
"""
7576
Render a field with its label
7677
"""
@@ -86,7 +87,7 @@ def render_field_and_label(field, label, field_class='', label_class='', layout=
8687
if field_class:
8788
html = '<div class="{klass}">{html}</div>'.format(klass=field_class, html=html)
8889
if label:
89-
html = render_label(label, label_class=label_class) + html
90+
html = render_label(label, label_for=label_for, label_class=label_class) + html
9091
return html
9192

9293

bootstrap3/renderers.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ class FieldRenderer(object):
8383
def __init__(self, field, layout='', form_group_class=FORM_GROUP_CLASS,
8484
field_class=None, label_class=None, show_label=True,
8585
show_help=True, exclude='', set_required=True,
86-
addon_before=None, addon_after=None):
86+
addon_before=None, addon_after=None,
87+
error_css_class='', required_css_class=''):
8788
# Only allow BoundField
8889
if not isinstance(field, BoundField):
8990
raise BootstrapError('Parameter "field" should contain a valid Django BoundField.')
@@ -101,11 +102,19 @@ def __init__(self, field, layout='', form_group_class=FORM_GROUP_CLASS,
101102
self.field_help = text_value(mark_safe(field.help_text)) if show_help and field.help_text else ''
102103
self.field_errors = [conditional_escape(text_value(error)) for error in field.errors]
103104
self.placeholder = field.label
104-
self.form_error_class = getattr(field.form, 'error_css_class', '')
105-
self.form_required_class = getattr(field.form, 'required_css_class', '')
106105
self.addon_before = addon_before
107106
self.addon_after = addon_after
108107

108+
# These are set in Django or in the global BOOTSTRAP3 settings, and they can be overwritten in the template
109+
if error_css_class:
110+
self.form_error_class = error_css_class
111+
else:
112+
self.form_error_class = getattr(field.form, 'error_css_class', get_bootstrap_setting('error_css_class'))
113+
if required_css_class:
114+
self.form_required_class = required_css_class
115+
else:
116+
self.form_required_class = getattr(field.form, 'required_css_class', get_bootstrap_setting('required_css_class'))
117+
109118
def restore_widget_attrs(self):
110119
self.widget.attrs = self.initial_attrs
111120

@@ -151,7 +160,7 @@ def list_to_class(self, html, klass):
151160

152161
def put_inside_label(self, html):
153162
content = '{field} {label}'.format(field=html, label=self.field.label)
154-
return render_label(content=content, label_title=strip_tags(self.field_help))
163+
return render_label(content=content, label_for=self.field.id_for_label, label_title=strip_tags(self.field_help))
155164

156165
def fix_date_select_input(self, html):
157166
div1 = '<div class="col-xs-4">'
@@ -248,7 +257,7 @@ def get_label(self):
248257
def add_label(self, html):
249258
label = self.get_label()
250259
if label:
251-
html = render_label(label, label_class=self.get_label_class()) + html
260+
html = render_label(label, label_for=self.field.id_for_label, label_class=self.get_label_class()) + html
252261
return html
253262

254263
def get_form_group_class(self):

bootstrap3/templatetags/bootstrap3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ def get_pagination_context(page, pages_to_show=11,
518518
url += force_text(extra) + '&'
519519
if url:
520520
url = url.replace('?&', '?')
521-
# Set CSS classes,see twitter.github.io/bootstrap/components.html#pagination
521+
# Set CSS classes, see http://getbootstrap.com/components/#pagination
522522
pagination_css_classes = ['pagination']
523523
if size == 'small':
524524
pagination_css_classes.append('pagination-sm')

bootstrap3/tests.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def clean(self):
7373
return cleaned_data
7474

7575

76+
class TestFormWithoutRequiredClass(TestForm):
77+
required_css_class = ''
78+
79+
7680
def render_template(text, **context_args):
7781
"""
7882
Create a template ``text`` that first loads bootstrap3.
@@ -211,6 +215,10 @@ def test_required_field(self):
211215
form_field = 'form.subject'
212216
rendered = render_template('{% bootstrap_field ' + form_field + ' set_required=0 %}')
213217
self.assertNotIn('required', rendered)
218+
# Required settings in field
219+
form_field = 'form.subject'
220+
rendered = render_template('{% bootstrap_field ' + form_field + ' required_css_class="test-required" %}')
221+
self.assertIn('test-required', rendered)
214222

215223
def test_input_group(self):
216224
res = render_template('{% bootstrap_field form.subject addon_before="$" addon_after=".00" %}')

demo/demo/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,6 @@
163163
# Settings for django-bootstrap3
164164
BOOTSTRAP3 = {
165165
'set_required': False,
166+
'form_error_class': 'bootstrap3-error',
167+
'form_required_class': 'bootstrap3-required',
166168
}

demo/demo/templates/demo/base.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ <h1>{% block title %}(no title){% endblock %}</h1>
1515
<a href="{% url 'form_inline' %}">form_inline</a>
1616
<a href="{% url 'form_with_files' %}">form_with_files</a>
1717
<a href="{% url 'pagination' %}">pagination</a>
18+
<a href="{% url 'misc' %}">miscellaneous</a>
1819
</p>
1920

2021
{% bootstrap_messages %}

demo/demo/templates/demo/misc.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends 'demo/base.html' %}
2+
3+
{% load bootstrap3 %}
4+
5+
{% block title %}
6+
Miscellaneous
7+
{% endblock %}
8+
9+
{% block content %}
10+
11+
{% bootstrap_button 'button' %}
12+
13+
{% endblock %}

demo/demo/urls.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.conf.urls import patterns, url
55

66
from .views import HomePageView, FormHorizontalView, FormInlineView, PaginationView, FormWithFilesView, \
7-
DefaultFormView
7+
DefaultFormView, MiscView
88

99
# Uncomment the next two lines to enable the admin:
1010
# from django.contrib import admin
@@ -27,6 +27,7 @@
2727
url(r'^form$', DefaultFormView.as_view(), name='form_default'),
2828
url(r'^form_horizontal$', FormHorizontalView.as_view(), name='form_horizontal'),
2929
url(r'^form_inline$', FormInlineView.as_view(), name='form_inline'),
30-
url(r'^pagination$', PaginationView.as_view(), name='pagination'),
3130
url(r'^form_with_files$', FormWithFilesView.as_view(), name='form_with_files'),
31+
url(r'^pagination$', PaginationView.as_view(), name='pagination'),
32+
url(r'^misc$', MiscView.as_view(), name='misc'),
3233
)

demo/demo/views.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,8 @@ def get_context_data(self, **kwargs):
7777
show_lines = paginator.page(paginator.num_pages)
7878
context['lines'] = show_lines
7979
return context
80+
81+
82+
class MiscView(TemplateView):
83+
template_name = 'demo/misc.html'
84+

0 commit comments

Comments
 (0)