Form validation
This commit is contained in:
@ -1,10 +1,20 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
from jinja2 import Environment
|
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):
|
def environment(**options):
|
||||||
env = Environment(**options)
|
env = Environment(**options)
|
||||||
|
|
||||||
env.globals.update({
|
env.globals.update({
|
||||||
# "url": reverse_url,
|
"conditional_cls": conditional_cls,
|
||||||
})
|
})
|
||||||
return env
|
return env
|
||||||
|
|||||||
@ -2,7 +2,18 @@
|
|||||||
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<p>
|
<form
|
||||||
This is some form validation content bellow.
|
hx-post="{{ url("form-validation") }}"
|
||||||
</p>
|
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 %}
|
{% endblock %}
|
||||||
|
|||||||
59
project/main/templates/main/form_validation_content.html
Normal file
59
project/main/templates/main/form_validation_content.html
Normal 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">
|
||||||
|
<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>
|
||||||
@ -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
|
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):
|
class FormValidationView(DemoViewBase):
|
||||||
template_name = "main/form_validation.html"
|
template_name = "main/form_validation.html"
|
||||||
active_section = "form-validation"
|
active_section = "form-validation"
|
||||||
title = "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,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user