• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zostera / django-bootstrap4 / 14820242235

04 May 2025 10:20AM UTC coverage: 90.728%. Remained the same
14820242235

Pull #813

github

web-flow
Merge 8ac7110cb into 7874abc4f
Pull Request #813: Symlink CHANGELOG.md into docs for Sphinx

233 of 302 branches covered (77.15%)

Branch coverage included in aggregate %.

1274 of 1359 relevant lines covered (93.75%)

14.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.45
/src/bootstrap4/forms.py
1
from django.forms import EmailInput, NumberInput, PasswordInput, Textarea, TextInput, URLInput
15✔
2
from django.utils.safestring import mark_safe
15✔
3

4
from .bootstrap import get_bootstrap_setting, get_field_renderer, get_form_renderer, get_formset_renderer
15✔
5
from .exceptions import BootstrapError
15✔
6
from .text import text_value
15✔
7
from .utils import add_css_class, render_tag
15✔
8

9
FORM_GROUP_CLASS = "form-group"
15✔
10

11

12
def render_formset(formset, **kwargs):
15✔
13
    """Render a formset to a Bootstrap layout."""
14
    renderer_cls = get_formset_renderer(**kwargs)
15✔
15
    return renderer_cls(formset, **kwargs).render()
15✔
16

17

18
def render_formset_errors(formset, **kwargs):
15✔
19
    """Render formset errors to a Bootstrap layout."""
20
    renderer_cls = get_formset_renderer(**kwargs)
×
21
    return renderer_cls(formset, **kwargs).render_errors()
×
22

23

24
def render_form(form, **kwargs):
15✔
25
    """Render a form to a Bootstrap layout."""
26
    renderer_cls = get_form_renderer(**kwargs)
15✔
27
    return renderer_cls(form, **kwargs).render()
15✔
28

29

30
def render_form_errors(form, type="all", **kwargs):
15✔
31
    """Render form errors to a Bootstrap layout."""
32
    renderer_cls = get_form_renderer(**kwargs)
×
33
    return renderer_cls(form, **kwargs).render_errors(type)
×
34

35

36
def render_field(field, **kwargs):
15✔
37
    """Render a field to a Bootstrap layout."""
38
    renderer_cls = get_field_renderer(**kwargs)
15✔
39
    return renderer_cls(field, **kwargs).render()
15✔
40

41

42
def render_label(content, label_for=None, label_class=None, label_title=""):
15✔
43
    """Render a label with content."""
44
    attrs = {}
15✔
45
    if label_for:
15✔
46
        attrs["for"] = label_for
15✔
47
    if label_class:
15✔
48
        attrs["class"] = label_class
15✔
49
    if label_title:
15✔
50
        attrs["title"] = label_title
15✔
51
    return render_tag("label", attrs=attrs, content=content)
15✔
52

53

54
def render_button(
15✔
55
    content,
56
    button_type=None,
57
    button_class="btn-primary",
58
    size="",
59
    href="",
60
    name=None,
61
    value=None,
62
    title=None,
63
    extra_classes="",
64
    id="",
65
):
66
    """Render a button with content."""
67
    attrs = {}
15✔
68
    classes = add_css_class("btn", button_class)
15✔
69
    size = text_value(size).lower().strip()
15✔
70
    if size == "xs":
15!
71
        classes = add_css_class(classes, "btn-xs")
×
72
    elif size == "sm" or size == "small":
15!
73
        classes = add_css_class(classes, "btn-sm")
×
74
    elif size == "lg" or size == "large":
15✔
75
        classes = add_css_class(classes, "btn-lg")
15✔
76
    elif size == "md" or size == "medium":
15!
77
        pass
×
78
    elif size:
15!
79
        raise BootstrapError(f'Parameter "size" should be "xs", "sm", "lg" or empty ("{size}" given).')
×
80

81
    if button_type:
15✔
82
        if button_type not in ("submit", "reset", "button", "link"):
15✔
83
            raise BootstrapError(
15✔
84
                'Parameter "button_type" should be "submit", "reset", "button", "link" or empty '
85
                f'("{button_type}" given).'
86
            )
87
        if button_type != "link":
15✔
88
            attrs["type"] = button_type
15✔
89

90
    classes = add_css_class(classes, extra_classes)
15✔
91
    attrs["class"] = classes
15✔
92

93
    if href:
15✔
94
        tag = "a"
15✔
95
        if button_type and button_type != "link":
15✔
96
            raise BootstrapError(f'Button of type "{button_type}" is not allowed a "href" parameter.')
15✔
97
        attrs["href"] = href
15✔
98
        # Specify role for link with button appearance
99
        attrs.setdefault("role", "button")
15✔
100
    else:
101
        tag = "button"
15✔
102

103
    if id:
15!
104
        attrs["id"] = id
×
105
    if name:
15!
106
        attrs["name"] = name
×
107
    if value:
15!
108
        attrs["value"] = value
×
109
    if title:
15!
110
        attrs["title"] = title
×
111
    return render_tag(tag, attrs=attrs, content=mark_safe(content))
15✔
112

113

114
def render_field_and_label(field, label, field_class="", label_for=None, label_class="", layout="", **kwargs):
15✔
115
    """Render a field with its label."""
116
    if layout == "horizontal":
15!
117
        if not label_class:
15!
118
            label_class = get_bootstrap_setting("horizontal_label_class")
15✔
119
        if not field_class:
15!
120
            field_class = get_bootstrap_setting("horizontal_field_class")
15✔
121
        if not label:
15!
122
            label = mark_safe(" ")
15✔
123
        label_class = add_css_class(label_class, "control-label")
15✔
124
    html = field
15✔
125
    if field_class:
15!
126
        html = f'<div class="{field_class}">{html}</div>'
15✔
127
    if label:
15!
128
        html = render_label(label, label_for=label_for, label_class=label_class) + html
15✔
129
    return html
15✔
130

131

132
def render_form_group(content, css_class=FORM_GROUP_CLASS):
15✔
133
    """Render a Bootstrap form group."""
134
    return f'<div class="{css_class}">{content}</div>'
15✔
135

136

137
def is_widget_with_placeholder(widget):
15✔
138
    """
139
    Return whether this widget should have a placeholder.
140

141
    Only text, text area, number, e-mail, url, password, number and derived inputs have placeholders.
142
    """
143
    return isinstance(widget, (TextInput, Textarea, NumberInput, EmailInput, URLInput, PasswordInput))
15✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc