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

zostera / django-bootstrap4 / 5399170771

pending completion
5399170771

push

github

dyve
Remove support for Python 3.7 (EOL)

272 of 344 branches covered (79.07%)

Branch coverage included in aggregate %.

704 of 793 relevant lines covered (88.78%)

3.55 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
4✔
2
from django.utils.safestring import mark_safe
4✔
3

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

9
FORM_GROUP_CLASS = "form-group"
4✔
10

11

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

17

18
def render_formset_errors(formset, **kwargs):
4✔
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):
4✔
25
    """Render a form to a Bootstrap layout."""
26
    renderer_cls = get_form_renderer(**kwargs)
4✔
27
    return renderer_cls(form, **kwargs).render()
4✔
28

29

30
def render_form_errors(form, type="all", **kwargs):
4✔
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):
4✔
37
    """Render a field to a Bootstrap layout."""
38
    renderer_cls = get_field_renderer(**kwargs)
4✔
39
    return renderer_cls(field, **kwargs).render()
4✔
40

41

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

53

54
def render_button(
4✔
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 = {}
4✔
68
    classes = add_css_class("btn", button_class)
4✔
69
    size = text_value(size).lower().strip()
4✔
70
    if size == "xs":
4!
71
        classes = add_css_class(classes, "btn-xs")
×
72
    elif size == "sm" or size == "small":
4!
73
        classes = add_css_class(classes, "btn-sm")
×
74
    elif size == "lg" or size == "large":
4✔
75
        classes = add_css_class(classes, "btn-lg")
4✔
76
    elif size == "md" or size == "medium":
4!
77
        pass
×
78
    elif size:
4!
79
        raise BootstrapError(f'Parameter "size" should be "xs", "sm", "lg" or empty ("{size}" given).')
×
80

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

92
    classes = add_css_class(classes, extra_classes)
4✔
93
    attrs["class"] = classes
4✔
94

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

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

115

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

133

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

138

139
def is_widget_with_placeholder(widget):
4✔
140
    """
141
    Return whether this widget should have a placeholder.
142

143
    Only text, text area, number, e-mail, url, password, number and derived inputs have placeholders.
144
    """
145
    return isinstance(widget, (TextInput, Textarea, NumberInput, EmailInput, URLInput, PasswordInput))
4✔
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