|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +from __future__ import unicode_literals |
| 3 | + |
| 4 | +from django.contrib.admin.widgets import AdminFileWidget |
| 5 | +from django.forms import ( |
| 6 | + HiddenInput, FileInput, CheckboxSelectMultiple, Textarea, TextInput |
| 7 | +) |
| 8 | + |
| 9 | +from .bootstrap import ( |
| 10 | + get_bootstrap_setting, get_form_renderer, get_field_renderer, |
| 11 | + get_formset_renderer |
| 12 | +) |
| 13 | +from .text import text_concat, text_value |
| 14 | +from .exceptions import BootstrapError |
| 15 | +from .utils import add_css_class, render_tag |
| 16 | +from .components import render_icon |
| 17 | + |
| 18 | + |
| 19 | +FORM_GROUP_CLASS = 'form-group' |
| 20 | + |
| 21 | + |
| 22 | +def render_formset(formset, **kwargs): |
| 23 | + """ |
| 24 | + Render a formset to a Bootstrap layout |
| 25 | + """ |
| 26 | + renderer_cls = get_formset_renderer(**kwargs) |
| 27 | + return renderer_cls(formset, **kwargs).render() |
| 28 | + |
| 29 | + |
| 30 | +def render_formset_errors(form, **kwargs): |
| 31 | + """ |
| 32 | + Render formset errors to a Bootstrap layout |
| 33 | + """ |
| 34 | + renderer_cls = get_formset_renderer(**kwargs) |
| 35 | + return renderer_cls(form, **kwargs).render_errors() |
| 36 | + |
| 37 | + |
| 38 | +def render_form(form, **kwargs): |
| 39 | + """ |
| 40 | + Render a formset to a Bootstrap layout |
| 41 | + """ |
| 42 | + renderer_cls = get_form_renderer(**kwargs) |
| 43 | + return renderer_cls(form, **kwargs).render() |
| 44 | + |
| 45 | + |
| 46 | +def render_form_errors(form, type='all', **kwargs): |
| 47 | + """ |
| 48 | + Render form errors to a Bootstrap layout |
| 49 | + """ |
| 50 | + renderer_cls = get_form_renderer(**kwargs) |
| 51 | + return renderer_cls(form, **kwargs).render_errors(type) |
| 52 | + |
| 53 | + |
| 54 | +def render_field(field, **kwargs): |
| 55 | + """ |
| 56 | + Render a formset to a Bootstrap layout |
| 57 | + """ |
| 58 | + renderer_cls = get_field_renderer(**kwargs) |
| 59 | + return renderer_cls(field, **kwargs).render() |
| 60 | + |
| 61 | + |
| 62 | +def render_label(content, label_for=None, label_class=None, label_title=''): |
| 63 | + """ |
| 64 | + Render a label with content |
| 65 | + """ |
| 66 | + attrs = {} |
| 67 | + if label_for: |
| 68 | + attrs['for'] = label_for |
| 69 | + if label_class: |
| 70 | + attrs['class'] = label_class |
| 71 | + if label_title: |
| 72 | + attrs['title'] = label_title |
| 73 | + return render_tag('label', attrs=attrs, content=content) |
| 74 | + |
| 75 | + |
| 76 | +def render_button( |
| 77 | + content, button_type=None, icon=None, button_class='', size='', |
| 78 | + href=''): |
| 79 | + """ |
| 80 | + Render a button with content |
| 81 | + """ |
| 82 | + attrs = {} |
| 83 | + classes = add_css_class('btn', button_class) |
| 84 | + size = text_value(size).lower().strip() |
| 85 | + if size == 'xs': |
| 86 | + classes = add_css_class(classes, 'btn-xs') |
| 87 | + elif size == 'sm' or size == 'small': |
| 88 | + classes = add_css_class(classes, 'btn-sm') |
| 89 | + elif size == 'lg' or size == 'large': |
| 90 | + classes = add_css_class(classes, 'btn-lg') |
| 91 | + elif size == 'md' or size == 'medium': |
| 92 | + pass |
| 93 | + elif size: |
| 94 | + raise BootstrapError( |
| 95 | + 'Parameter "size" should be "xs", "sm", "lg" or ' + |
| 96 | + 'empty ("{}" given).'.format(size)) |
| 97 | + if button_type: |
| 98 | + if button_type == 'submit': |
| 99 | + classes = add_css_class(classes, 'btn-primary') |
| 100 | + elif button_type not in ('reset', 'button', 'link'): |
| 101 | + raise BootstrapError( |
| 102 | + 'Parameter "button_type" should be "submit", "reset", ' + |
| 103 | + '"button", "link" or empty ("{}" given).'.format(button_type)) |
| 104 | + attrs['type'] = button_type |
| 105 | + attrs['class'] = classes |
| 106 | + icon_content = render_icon(icon) if icon else '' |
| 107 | + if href: |
| 108 | + attrs['href'] = href |
| 109 | + tag = 'a' |
| 110 | + else: |
| 111 | + tag = 'button' |
| 112 | + return render_tag( |
| 113 | + tag, attrs=attrs, content=text_concat( |
| 114 | + icon_content, content, separator=' ')) |
| 115 | + |
| 116 | + |
| 117 | +def render_field_and_label( |
| 118 | + field, label, field_class='', label_for=None, label_class='', |
| 119 | + layout='', **kwargs): |
| 120 | + """ |
| 121 | + Render a field with its label |
| 122 | + """ |
| 123 | + if layout == 'horizontal': |
| 124 | + if not label_class: |
| 125 | + label_class = get_bootstrap_setting('horizontal_label_class') |
| 126 | + if not field_class: |
| 127 | + field_class = get_bootstrap_setting('horizontal_field_class') |
| 128 | + if not label: |
| 129 | + label = ' ' |
| 130 | + label_class = add_css_class(label_class, 'control-label') |
| 131 | + html = field |
| 132 | + if field_class: |
| 133 | + html = '<div class="{klass}">{html}</div>'.format( |
| 134 | + klass=field_class, html=html) |
| 135 | + if label: |
| 136 | + html = render_label( |
| 137 | + label, label_for=label_for, label_class=label_class) + html |
| 138 | + return html |
| 139 | + |
| 140 | + |
| 141 | +def render_form_group(content, css_class=FORM_GROUP_CLASS): |
| 142 | + """ |
| 143 | + Render a Bootstrap form group |
| 144 | + """ |
| 145 | + return '<div class="{klass}">{content}</div>'.format( |
| 146 | + klass=css_class, |
| 147 | + content=content, |
| 148 | + ) |
| 149 | + |
| 150 | + |
| 151 | +def is_widget_required_attribute(widget): |
| 152 | + """ |
| 153 | + Is this widget required? |
| 154 | + """ |
| 155 | + if not get_bootstrap_setting('set_required'): |
| 156 | + return False |
| 157 | + if not widget.is_required: |
| 158 | + return False |
| 159 | + if isinstance( |
| 160 | + widget, ( |
| 161 | + AdminFileWidget, HiddenInput, FileInput, |
| 162 | + CheckboxSelectMultiple)): |
| 163 | + return False |
| 164 | + return True |
| 165 | + |
| 166 | + |
| 167 | +def is_widget_with_placeholder(widget): |
| 168 | + """ |
| 169 | + Is this a widget that should have a placeholder? |
| 170 | + Only text, search, url, tel, e-mail, password, number have placeholders |
| 171 | + These are all derived form TextInput, except for Textarea |
| 172 | + """ |
| 173 | + return isinstance(widget, (TextInput, Textarea)) |
0 commit comments