__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
from django import forms
from django.template.loader import get_template
from django import template
from dal import autocomplete
register = template.Library()
# Custom filter originally created by tzangms
# and customized for use with Bootstrap 4.x
# https://github.com/tzangms/django-bootstrap-form
# Own tweaks
[docs]@register.filter
def bootstrap(element, args="2,10", extra_classes=""):
"""Pass arguments to tag by separating them using a comma ",".
Arguments:
-- 1. Column width for label
-- 2. Column width for input
-- 3. Additional argument 'sm' or 'lg' for form groups.
"""
args = dict(enumerate(args.split(",")))
markup_classes = {
"label": "col-md-%s" % args.get(0, "4"),
"value": "col-md-%s" % args.get(1, "8"),
"single_value": args.get(2, "col-12"),
"form_control": "",
}
if args.get(2, False):
markup_classes["label"] += " col-form-label-%s" % args.get(2)
markup_classes["form_control"] = "form-control-%s" % args.get(2)
if extra_classes:
markup_classes["extra"] = extra_classes
return render(element, markup_classes)
[docs]@register.filter
def bootstrap_inline(element, args="2,10"):
args = [arg.strip() for arg in args.split(",")]
markup_classes = {
"label": "visually-hidden col-md-%s" % args[0],
"value": "col-md-%s" % args[1],
"single_value": "",
}
try:
markup_classes["label"] += " col-form-label-%s" % args[2]
markup_classes["form_control"] = "form-control-%s" % args[2]
except IndexError:
markup_classes["form_control"] = ""
return render(element, markup_classes)
[docs]@register.filter
def bootstrap_grouped(element, args="2,10"):
return bootstrap(element, args, "grouped")
[docs]@register.filter
def add_css_class(field, extra_class):
"""Add additional CSS classes to a field in the template."""
if (
not is_autocomplete(field)
and not is_checkbox(field)
and not is_multiple_checkbox(field)
and not is_radio(field)
and not is_file(field)
):
field_classes = field.field.widget.attrs.get("class", "")
field_classes += " " + extra_class
field.field.widget.attrs["class"] = field_classes
return ""
[docs]def render(element, markup_classes):
element_type = element.__class__.__name__.lower()
if element_type == "boundfield":
add_input_classes(element, markup_classes["form_control"])
template = get_template("tags/bootstrap/field.html")
context = {"field": element, "classes": markup_classes, "form": element.form}
else:
has_management = getattr(element, "management_form", None)
if has_management:
for form in element.forms:
for field in form.visible_fields():
add_input_classes(field, markup_classes["form_control"])
template = get_template("tags/bootstrap/formset.html")
context = {"formset": element, "classes": markup_classes}
else:
for field in element.visible_fields():
add_input_classes(field, markup_classes["form_control"])
template = get_template("tags/bootstrap/form.html")
context = {"form": element, "classes": markup_classes}
return template.render(context)
[docs]@register.filter
def is_autocomplete(field):
return isinstance(field.field.widget, autocomplete.ModelSelect2) or isinstance(
field.field.widget, autocomplete.ModelSelect2Multiple
)
[docs]@register.filter
def is_checkbox(field):
return isinstance(field.field.widget, forms.CheckboxInput)
[docs]@register.filter
def is_multiple_checkbox(field):
return isinstance(field.field.widget, forms.CheckboxSelectMultiple)
[docs]@register.filter
def is_radio(field):
return isinstance(field.field.widget, forms.RadioSelect)
[docs]@register.filter
def is_file(field):
return isinstance(field.field.widget, forms.FileInput)