Skip to content

Commit 2d8f1e4

Browse files
committed
Merge branch 'release/4.9.0'
2 parents b93cdfe + 358cc11 commit 2d8f1e4

File tree

8 files changed

+68
-19
lines changed

8 files changed

+68
-19
lines changed

HISTORY.rst

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

66

7+
4.9.0 (2014-08-09)
8+
++++++++++++++++++
9+
10+
* New parameter `href` for `bootstrap_button`, if provided will render `a` tag instead of `buttonz tag
11+
12+
713
4.8.2 (2014-07-10)
814
++++++++++++++++++
915

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.8.2'
3+
__version__ = '4.9.0'

bootstrap3/bootstrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
'set_placeholder': True,
2121
'form_required_class': '',
2222
'form_error_class': '',
23-
'formset_renderers':{
23+
'formset_renderers': {
2424
'default': 'bootstrap3.renderers.FormsetRenderer',
2525
},
2626
'form_renderers': {

bootstrap3/forms.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def render_label(content, label_for=None, label_class=None, label_title=''):
6868
return render_tag('label', attrs=attrs, content=content)
6969

7070

71-
def render_button(content, button_type=None, icon=None, button_class='', size=''):
71+
def render_button(content, button_type=None, icon=None, button_class='', size='', href=''):
7272
"""
7373
Render a button with content
7474
"""
@@ -88,12 +88,17 @@ def render_button(content, button_type=None, icon=None, button_class='', size=''
8888
if button_type:
8989
if button_type == 'submit':
9090
classes = add_css_class(classes, 'btn-primary')
91-
elif button_type != 'reset' and button_type != 'button':
92-
raise BootstrapError('Parameter "button_type" should be "submit", "reset", "button" or empty.')
91+
elif not button_type in ('reset' 'button', 'link'):
92+
raise BootstrapError('Parameter "button_type" should be "submit", "reset", "button", "link" or empty.')
9393
attrs['type'] = button_type
9494
attrs['class'] = classes
9595
icon_content = render_icon(icon) if icon else ''
96-
return render_tag('button', attrs=attrs, content=text_concat(icon_content, content, separator=' '))
96+
if href:
97+
attrs['href'] = href
98+
tag = 'a'
99+
else:
100+
tag = 'button'
101+
return render_tag(tag, attrs=attrs, content=text_concat(icon_content, content, separator=' '))
97102

98103

99104
def render_field_and_label(field, label, field_class='', label_for=None, label_class='', layout='', **kwargs):

bootstrap3/html.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def render_link_tag(url, rel='stylesheet', media='all'):
4343
"""
4444
Build a link tag
4545
"""
46-
return render_tag('link', attrs = {'href': url, 'rel': rel, 'media': media}, close=False)
46+
return render_tag('link', attrs={'href': url, 'rel': rel, 'media': media}, close=False)
4747

4848

4949
def render_tag(tag, attrs=None, content=None, close=True):

bootstrap3/renderers.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import unicode_literals
3+
from django.contrib.auth.forms import ReadOnlyPasswordHashWidget
34

45
from django.forms import (TextInput, DateInput, FileInput, CheckboxInput,
56
ClearableFileInput, Select, RadioSelect, CheckboxSelectMultiple)
@@ -94,7 +95,8 @@ def render_errors(self):
9495
'errors': formset_errors,
9596
'form': self.formset,
9697
'layout': self.layout,
97-
}))
98+
})
99+
)
98100
return ''
99101

100102
def render(self):
@@ -111,6 +113,9 @@ def __init__(self, form, *args, **kwargs):
111113
raise BootstrapError('Parameter "form" should contain a valid Django Form.')
112114
self.form = form
113115
super(FormRenderer, self).__init__(*args, **kwargs)
116+
# Handle form.empty_permitted
117+
if self.form.empty_permitted:
118+
self.set_required = False
114119

115120
def render_fields(self):
116121
rendered_fields = []
@@ -193,16 +198,22 @@ def __init__(self, field, *args, **kwargs):
193198
else:
194199
self.form_required_class = getattr(field.form, 'required_css_class',
195200
get_bootstrap_setting('required_css_class'))
201+
# Handle form.empty_permitted
202+
if self.field.form.empty_permitted:
203+
self.set_required = False
204+
self.form_required_class = ''
196205

197206
def restore_widget_attrs(self):
198207
self.widget.attrs = self.initial_attrs
199208

200209
def add_class_attrs(self):
201210
classes = self.widget.attrs.get('class', '')
202-
if not isinstance(self.widget, (CheckboxInput,
203-
RadioSelect,
204-
CheckboxSelectMultiple,
205-
FileInput)):
211+
if isinstance(self.widget, ReadOnlyPasswordHashWidget):
212+
classes = add_css_class(classes, 'form-control-static', prepend=True)
213+
elif not isinstance(self.widget, (CheckboxInput,
214+
RadioSelect,
215+
CheckboxSelectMultiple,
216+
FileInput)):
206217
classes = add_css_class(classes, 'form-control', prepend=True)
207218
# For these widget types, add the size class here
208219
classes = add_css_class(classes, self.get_size_class())
@@ -350,8 +361,7 @@ def get_form_group_class(self):
350361
form_group_class = add_css_class(
351362
form_group_class, self.form_error_class)
352363
if self.field.field.required and self.form_required_class:
353-
form_group_class = add_css_class(
354-
form_group_class, self.form_required_class)
364+
form_group_class = add_css_class(form_group_class, self.form_required_class)
355365
if self.field_errors:
356366
form_group_class = add_css_class(form_group_class, 'has-error')
357367
elif self.field.form.is_bound:

bootstrap3/tests.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from django import forms
55
from django.template import Template, Context
66
from django.utils.unittest import TestCase
7+
from bootstrap3.text import text_value, text_concat
78

89
from .exceptions import BootstrapError
910

@@ -229,6 +230,15 @@ def test_required_field(self):
229230
rendered = render_template('{% bootstrap_field ' + form_field + ' required_css_class="test-required" %}')
230231
self.assertIn('test-required', rendered)
231232

233+
def test_empty_permitted(self):
234+
form = TestForm()
235+
res = render_form_field('subject', form=form)
236+
self.assertIn('required', res)
237+
form.empty_permitted = True
238+
res = render_form_field('subject', form=form)
239+
self.assertNotIn('required', res)
240+
241+
232242
def test_input_group(self):
233243
res = render_template('{% bootstrap_field form.subject addon_before="$" addon_after=".00" %}')
234244
self.assertIn('class="input-group"', res)
@@ -308,7 +318,7 @@ def __str__(self):
308318
self.assertEqual(res.strip(), expected.strip())
309319

310320

311-
class HtmlTest(TestCase):
321+
class TextTest(TestCase):
312322
def test_add_css_class(self):
313323
css_classes = "one two"
314324
css_class = "three four"
@@ -317,3 +327,24 @@ def test_add_css_class(self):
317327

318328
classes = add_css_class(css_classes, css_class, prepend=True)
319329
self.assertEqual(classes, "three four one two")
330+
331+
332+
class HtmlTest(TestCase):
333+
def test_text_value(self):
334+
self.assertEqual(text_value(''), "")
335+
self.assertEqual(text_value(' '), " ")
336+
self.assertEqual(text_value(None), "")
337+
self.assertEqual(text_value(1), "1")
338+
339+
def test_text_concat(self):
340+
self.assertEqual(text_concat(1, 2), "12")
341+
self.assertEqual(text_concat(1, 2, separator='='), "1=2")
342+
self.assertEqual(text_concat(None, 2, separator='='), "2")
343+
344+
345+
class ButtonTest(TestCase):
346+
def test_button(self):
347+
res = render_template("{% bootstrap_button 'button' size='lg' %}")
348+
self.assertEqual(res.strip(), '<button class="btn btn-lg">button</button>')
349+
res = render_template("{% bootstrap_button 'button' size='lg' href='#' %}")
350+
self.assertEqual(res.strip(), '<a class="btn btn-lg" href="#">button</a>')

bootstrap3/text.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,5 @@ def text_concat(*args, **kwargs):
2222
Concatenate several values as a text string with an optional separator
2323
"""
2424
separator = text_value(kwargs.get('separator', ''))
25-
skip_empty = kwargs.get('skip_empty', False)
26-
values = [text_value(v) for v in args]
27-
if skip_empty:
28-
values = [v for v in values if v]
25+
values = filter(None, [text_value(v) for v in args])
2926
return separator.join(values)

0 commit comments

Comments
 (0)