Build template-based form rendering with bootstrap attrs
This commit is contained in:
parent
eb91f59e09
commit
78119dc6b3
5 changed files with 79 additions and 1 deletions
28
src/servala/frontend/forms/renderers.py
Normal file
28
src/servala/frontend/forms/renderers.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from django.forms.renderers import TemplatesSetting
|
||||||
|
|
||||||
|
|
||||||
|
def inject_class(f, class_name):
|
||||||
|
def inner(*args, **kwargs):
|
||||||
|
result = f(*args, **kwargs)
|
||||||
|
class_list = result.get("class", "")
|
||||||
|
class_list = f"{class_list} {class_name}".strip()
|
||||||
|
result["class"] = class_list
|
||||||
|
return result
|
||||||
|
|
||||||
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
class VerticalFormRenderer(TemplatesSetting):
|
||||||
|
form_template_name = "frontend/forms/form.html"
|
||||||
|
field_template_name = "frontend/forms/vertical_field.html"
|
||||||
|
|
||||||
|
def render(self, template_name, context, request=None):
|
||||||
|
if field := context.get("field"):
|
||||||
|
if field.field.widget.input_type == "checkbox":
|
||||||
|
class_name = "form-check-input"
|
||||||
|
else:
|
||||||
|
class_name = "form-control"
|
||||||
|
field.build_widget_attrs = inject_class(
|
||||||
|
field.build_widget_attrs, class_name
|
||||||
|
)
|
||||||
|
return super().render(template_name, context, request)
|
|
@ -37,7 +37,10 @@
|
||||||
<i class="bi bi-chevron-right me-2 ms-1 mb-2 collapse-icon"></i>
|
<i class="bi bi-chevron-right me-2 ms-1 mb-2 collapse-icon"></i>
|
||||||
{% translate "Log in with email and password instead" %}
|
{% translate "Log in with email and password instead" %}
|
||||||
</a>
|
</a>
|
||||||
<div class="collapse mt-3" id="login-form">
|
<div class="collapse mt-3 ms-3"
|
||||||
|
id="login-form"
|
||||||
|
class="form form-vertical"
|
||||||
|
style="max-width: 400px">
|
||||||
<form method="post" action="{% url 'account_login' %}">
|
<form method="post" action="{% url 'account_login' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
|
|
19
src/servala/frontend/templates/frontend/forms/form.html
Normal file
19
src/servala/frontend/templates/frontend/forms/form.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{% if errors %}
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<div>
|
||||||
|
{% if errors|length > 1 %}
|
||||||
|
<ul>
|
||||||
|
{% for error in errors %}<li>{{ error }}</li>{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
{{ errors.0 }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="form-body">
|
||||||
|
<div class="row">
|
||||||
|
{% for field, errors in fields %}{{ field.as_field_group }}{% endfor %}
|
||||||
|
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,26 @@
|
||||||
|
{% load i18n %}
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-group{% with classes=field.css_classes %}{% if classes %} {{ classes }}{% endif %}{% endwith %}">
|
||||||
|
{% if field.field.widget.input_type != "checkbox" or field.field.widget.allow_multiple_selected %}
|
||||||
|
<label for="{{ field.auto_id }}" class="{{ label_class }}">
|
||||||
|
{{ field.label }}
|
||||||
|
{% if not field.field.required %}
|
||||||
|
<span class="optional">{% translate "Optional" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
{% if field.use_fieldset %}
|
||||||
|
<fieldset {% if field.help_text and field.auto_id and "aria-describedby" not in field.field.widget.attrs %} aria-describedby="{{ field.auto_id }}_helptext"{% endif %}>
|
||||||
|
{% endif %}
|
||||||
|
{{ field }}
|
||||||
|
{% if field.field.widget.input_type == "checkbox" and not field.field.widget.allow_multiple_selected %}
|
||||||
|
<label for="{{ field.auto_id }}">{{ field.label }}</label>
|
||||||
|
{% endif %}
|
||||||
|
{% if field.use_fieldset %}</fieldset>{% endif %}
|
||||||
|
{% for text in field.errors %}<div class="invalid-feedback">{{ text }}</div>{% endfor %}
|
||||||
|
{% if field.help_text %}
|
||||||
|
<small class="form-text text-muted"
|
||||||
|
{% if field.auto_id %}id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</small>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -95,6 +95,7 @@ INSTALLED_APPS = [
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
"django.contrib.messages",
|
"django.contrib.messages",
|
||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
|
"django.forms",
|
||||||
"servala.frontend",
|
"servala.frontend",
|
||||||
"allauth",
|
"allauth",
|
||||||
"allauth.account",
|
"allauth.account",
|
||||||
|
@ -151,6 +152,7 @@ TEMPLATES = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
FORM_RENDERER = "servala.frontend.forms.renderers.VerticalFormRenderer"
|
||||||
MESSAGE_TAGS = {
|
MESSAGE_TAGS = {
|
||||||
messages.ERROR: "danger",
|
messages.ERROR: "danger",
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue