Ответ
Валидацию данных в веб-приложениях принято разделять на несколько уровней. Такой многоуровневый подход обеспечивает надежность и хороший пользовательский опыт.
1. Клиентский уровень (Frontend)
Проверка данных происходит в браузере пользователя до отправки на сервер.
- Цель: Улучшить UX, предоставив мгновенную обратную связь (например, поле email заполнено неверно).
- Технологии: Атрибуты HTML5 (
required,pattern), JavaScript. - Важно: Этот уровень легко обойти, поэтому он никогда не должен быть единственным.
<form>
<input type="email" name="email" required>
<input type="number" name="age" min="18">
</form>
2. Серверный уровень (Backend)
Это основной и обязательный уровень валидации. Проверка происходит после получения данных от клиента.
- Цель: Обеспечить целостность и безопасность данных, так как эту проверку нельзя обойти.
- Технологии: Библиотеки вроде Pydantic (Python), Joi (Node.js), встроенные средства фреймворков (Django Forms, DRF Serializers).
# Пример с Pydantic в FastAPI
from pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
email: EmailStr
age: int = Field(gt=18, description="Возраст должен быть больше 18")
3. Уровень бизнес-логики
Проверка данных в контексте правил конкретного приложения, которые не могут быть выражены простыми типами.
- Цель: Гарантировать соответствие данных бизнес-требованиям.
- Примеры: Проверка, что баланс пользователя достаточен для совершения покупки; проверка, что промокод еще действителен.
class OrderService:
def create_order(self, user: User, order_data: Order):
if user.balance < order_data.total_price:
raise ValueError("Недостаточно средств на счете")
# ... логика создания заказа
4. Уровень базы данных (Database)
Последний рубеж защиты целостности данных, реализованный на уровне СУБД.
- Цель: Предотвратить запись некорректных данных даже в обход логики приложения.
- Технологии: Ограничения (
constraints)UNIQUE,NOT NULL,CHECK, внешние ключи (FOREIGN KEY).
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
age INTEGER CHECK (age > 0)
);