Form validation

This commit is contained in:
Eden Kirin
2024-04-06 18:21:50 +02:00
parent f2dc83caab
commit b146b430cc
4 changed files with 143 additions and 4 deletions

View File

@ -1,10 +1,20 @@
from typing import Any
from jinja2 import Environment
def conditional_cls(conditions: dict[str, Any]) -> str:
result = []
for cls, condition in conditions.items():
if condition:
result.append(cls)
return " ".join(result)
def environment(**options):
env = Environment(**options)
env.globals.update({
# "url": reverse_url,
"conditional_cls": conditional_cls,
})
return env

View File

@ -2,7 +2,18 @@
{% block content %}
<p>
This is some form validation content bellow.
</p>
<form
hx-post="{{ url("form-validation") }}"
hx-target="#validation-form-content"
hx-swap="outerHTML"
>
<div class="card p-4">
{% include "main/form_validation_content.html" %}
<div class="d-flex">
<button type="submit" class="btn btn-success ms-auto">
Submit
</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,59 @@
<div id="validation-form-content">
<div class="row">
<div class="col">
<div class="mb-3">
<label for="validation-form-number" class="form-label">Enter name, length 3..10</label>
<input
type="text"
class="form-control {{ conditional_cls({
"is-invalid": validation.name_error,
"is-valid": validation.validated and not validation.name_error,
}) }}"
name="name"
id="validation-form-number"
value="{{ validation.name | default_if_none("") }}"
/>
{% if validation.name_error %}
<div class="invalid-feedback">{{ validation.name_error }}</div>
{% endif %}
</div>
</div>
<div class="col">
<div class="mb-3">
<label for="validation-form-number" class="form-label">Enter age, 1..100</label>
<input
type="text"
class="form-control {{ conditional_cls({
"is-invalid": validation.age_error,
"is-valid": validation.validated and not validation.age_error,
}) }}"
name="age"
id="validation-form-number"
value="{{ validation.age | default_if_none("") }}"
/>
{% if validation.age_error %}
<div class="invalid-feedback">{{ validation.age_error }}</div>
{% endif %}
</div>
</div>
</div>
<div class="form-check form-switch">
<input
class="form-check-input {{ conditional_cls({
"is-invalid": validation.consent_error,
"is-valid": validation.validated and not validation.consent_error,
}) }}"
type="checkbox"
name="consent"
id="consent-checkbox"
{% if validation.consent %}checked{% endif %}
>
<label class="form-check-label" for="consent-checkbox">
I consent to use this data for what ever you want
</label>
{% if validation.consent_error %}
<div class="invalid-feedback">{{ validation.consent_error }}</div>
{% endif %}
</div>
</div>

View File

@ -1,7 +1,66 @@
from dataclasses import dataclass
from typing import Any, Optional
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpResponse
from django.shortcuts import render
from project.main.views.demo_view_base import DemoViewBase
@dataclass
class Validation:
validated: bool = False
name: Optional[str] = None
consent: Optional[bool] = None
age: Optional[int] = None
name_error: Optional[str] = None
age_error: Optional[str] = None
consent_error: Optional[str] = None
class FormValidationView(DemoViewBase):
template_name = "main/form_validation.html"
active_section = "form-validation"
title = "Form Validation"
def get_context_data(self, **kwargs) -> dict[str, Any]:
context = super().get_context_data(**kwargs)
context.update(
{
"validation": Validation(),
}
)
return context
def post(self, request: WSGIRequest, *args, **kwargs) -> HttpResponse:
validation = Validation(
validated=True,
name=request.POST.get("name", ""),
age=request.POST.get("age", ""),
consent=request.POST.get("consent") == "on",
)
if len(validation.name) < 3 or len(validation.name) > 10:
validation.name_error = "Name must be between 3 and 10 chars long"
try:
age = int(validation.age)
except ValueError:
validation.age_error = "Invalid integer"
else:
if age < 1 or age > 100:
validation.age_error = "Age should be between 1 and 100"
if not validation.consent:
validation.consent_error = "You should consent"
return render(
context={
"validation": validation,
},
template_name="main/form_validation_content.html",
request=request,
)