- Добавлены ManyToMany поля: departments, recipients, cc_users, sent_to_all_department - Старое поле department сохранено для обратной совместимости - Создана миграция с автоматическим переносом данных - Обновлены сериализаторы RequestReadSerializer и RequestWriteSerializer - Добавлен RecipientIDsField для поддержки разных форматов - Добавлены методы is_recipient, add_recipient, remove_recipient в модель - Добавлена валидация получателей и отделов
216 lines
9.5 KiB
Markdown
216 lines
9.5 KiB
Markdown
# Валидация полей ФИО в форме регистрации
|
||
|
||
## Описание
|
||
Добавлена валидация для полей "Имя", "Фамилия" и "Отчество", запрещающая ввод цифр.
|
||
|
||
## Изменённые файлы
|
||
|
||
### 1. `backend/employees/forms_auth.py`
|
||
|
||
Добавлены методы валидации на уровне Django формы:
|
||
|
||
- **`clean_first_name()`** - валидация имени
|
||
- **`clean_last_name()`** - валидация фамилии
|
||
- **`clean_patronymic()`** - валидация отчества
|
||
|
||
#### Правила валидации:
|
||
- ✅ Разрешены: буквы любых алфавитов, пробелы, дефисы, апострофы
|
||
- ❌ Запрещены: цифры (0-9)
|
||
- Отчество - опциональное поле (может быть пустым)
|
||
|
||
#### Проверки:
|
||
```python
|
||
# Проверка на наличие цифр
|
||
if re.search(r'\d', value):
|
||
raise forms.ValidationError("Имя не должно содержать цифры.")
|
||
|
||
# Разрешённые символы: буквы, пробелы, дефисы, апострофы
|
||
if not re.match(r'^[\w\s\-\']+$', value, re.UNICODE):
|
||
raise forms.ValidationError(
|
||
"Имя может содержать только буквы, пробелы, дефисы и апострофы."
|
||
)
|
||
```
|
||
|
||
### 2. `backend/api/v1/employees/serializers.py`
|
||
|
||
Добавлены методы валидации на уровне DRF API:
|
||
|
||
- **`validate_first_name()`** - валидация имени через API
|
||
- **`validate_last_name()`** - валидация фамилии через API
|
||
- **`validate_patronymic()`** - валидация отчества через API
|
||
|
||
Использует те же правила, что и Django формы. Защищает API от некорректных данных при прямых запросах.
|
||
|
||
```python
|
||
def validate_first_name(self, value: str) -> str:
|
||
"""Валидация имени: только буквы, пробелы и дефисы."""
|
||
value = value.strip()
|
||
if not value:
|
||
raise serializers.ValidationError("Имя обязательно для заполнения.")
|
||
if re.search(r'\d', value):
|
||
raise serializers.ValidationError("Имя не должно содержать цифры.")
|
||
if not re.match(r'^[\w\s\-\']+$', value, re.UNICODE):
|
||
raise serializers.ValidationError(
|
||
"Имя может содержать только буквы, пробелы, дефисы и апострофы."
|
||
)
|
||
return value
|
||
```
|
||
|
||
### 3. `backend/templates/auth/register.html`
|
||
|
||
Добавлены правила клиентской валидации (real-time):
|
||
|
||
#### Для имени:
|
||
```javascript
|
||
first_name: [
|
||
{ type: 'required', message: 'Имя обязательно для заполнения' },
|
||
{ type: 'minLength', value: 2, message: 'Минимум 2 символа' },
|
||
{
|
||
type: 'pattern',
|
||
pattern: /^[^\d]+$/,
|
||
message: 'Имя не должно содержать цифры'
|
||
}
|
||
]
|
||
```
|
||
|
||
#### Для фамилии:
|
||
```javascript
|
||
last_name: [
|
||
{ type: 'required', message: 'Фамилия обязательна для заполнения' },
|
||
{ type: 'minLength', value: 2, message: 'Минимум 2 символа' },
|
||
{
|
||
type: 'pattern',
|
||
pattern: /^[^\d]+$/,
|
||
message: 'Фамилия не должна содержать цифры'
|
||
}
|
||
]
|
||
```
|
||
|
||
#### Для отчества:
|
||
```javascript
|
||
patronymic: [
|
||
{
|
||
type: 'pattern',
|
||
pattern: /^[^\d]*$/,
|
||
message: 'Отчество не должно содержать цифры'
|
||
}
|
||
]
|
||
```
|
||
|
||
**Примечание:** Для отчества используется `/^[^\d]*$/` (звёздочка вместо плюса), потому что поле опциональное и может быть пустым.
|
||
|
||
## Как работает валидация
|
||
|
||
### Уровень 1: Клиентская валидация (JavaScript)
|
||
- Работает в режиме реального времени через `liveValidationHandler.js`
|
||
- Показывает ошибку сразу при вводе цифр
|
||
- Используется регулярное выражение `/^[^\d]+$/` (запрещает любые цифры)
|
||
|
||
### Уровень 2: Серверная валидация (Django Forms)
|
||
- Срабатывает при отправке формы через веб-интерфейс
|
||
- Методы `clean_first_name()`, `clean_last_name()`, `clean_patronymic()`
|
||
- Проверяет отсутствие цифр через `re.search(r'\d', value)`
|
||
- Также проверяет допустимые символы через regex pattern
|
||
|
||
### Уровень 3: API валидация (DRF Serializers)
|
||
- Срабатывает при прямых запросах к API
|
||
- Методы `validate_first_name()`, `validate_last_name()`, `validate_patronymic()`
|
||
- Использует те же правила, что и Django формы
|
||
- Защищает от обхода клиентской валидации
|
||
|
||
## Поведение
|
||
|
||
### Разрешённые имена:
|
||
- ✅ "Иван"
|
||
- ✅ "Мария-Анна" (дефис)
|
||
- ✅ "О'Брайан" (апостроф)
|
||
- ✅ "Анна Мария" (пробел)
|
||
- ✅ "Jean-Claude" (латиница с дефисом)
|
||
|
||
### Запрещённые имена:
|
||
- ❌ "Иван123" (содержит цифры)
|
||
- ❌ "Мария1" (содержит цифры)
|
||
- ❌ "3D-Петр" (начинается с цифры)
|
||
|
||
## Сообщения об ошибках
|
||
|
||
### Клиентская валидация:
|
||
- "Имя не должно содержать цифры"
|
||
- "Фамилия не должна содержать цифры"
|
||
- "Отчество не должно содержать цифры"
|
||
|
||
### Серверная валидация:
|
||
- "Имя не должно содержать цифры."
|
||
- "Фамилия не должна содержать цифры."
|
||
- "Отчество не должно содержать цифры."
|
||
- "Имя может содержать только буквы, пробелы, дефисы и апострофы."
|
||
- "Фамилия может содержать только буквы, пробелы, дефисы и апострофы."
|
||
- "Отчество может содержать только буквы, пробелы, дефисы и апострофы."
|
||
|
||
## Технические детали
|
||
|
||
### Регулярные выражения:
|
||
|
||
**JavaScript (клиент):**
|
||
- `/^[^\d]+$/` - для обязательных полей (имя, фамилия)
|
||
- `/^[^\d]*$/` - для опциональных полей (отчество)
|
||
|
||
**Python (сервер):**
|
||
- `r'\d'` - поиск любых цифр
|
||
- `r'^[\w\s\-\']+$'` с флагом `re.UNICODE` - проверка допустимых символов
|
||
|
||
### Импорты:
|
||
```python
|
||
# backend/employees/forms_auth.py
|
||
import re # Добавлен в imports
|
||
|
||
# backend/api/v1/employees/serializers.py
|
||
import re # Добавлен в imports
|
||
```
|
||
|
||
## Тестирование
|
||
|
||
Проверьте следующие сценарии:
|
||
|
||
1. **Попытка ввести цифры в имя** → должна появиться ошибка
|
||
2. **Попытка ввести цифры в фамилию** → должна появиться ошибка
|
||
3. **Попытка ввести цифры в отчество** → должна появиться ошибка
|
||
4. **Ввод имени с дефисом "Анна-Мария"** → должно пройти валидацию
|
||
5. **Пустое отчество** → должно пройти валидацию (поле опциональное)
|
||
6. **Имя с латиницей "John"** → должно пройти валидацию
|
||
|
||
## Связанные файлы
|
||
|
||
- `backend/static/js/components/liveValidationHandler.js` - модуль live validation
|
||
- `backend/employees/forms_auth.py` - Django формы регистрации
|
||
- `backend/api/v1/employees/serializers.py` - DRF сериализаторы для API
|
||
|
||
## Архитектура валидации
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ REGISTRATION FLOW │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
|
||
User Input (Browser)
|
||
↓
|
||
┌─────────────────────┐
|
||
│ Level 1: JavaScript │ → liveValidationHandler.js
|
||
│ Real-time check │ → Pattern: /^[^\d]+$/
|
||
└─────────────────────┘
|
||
↓ (submit)
|
||
┌─────────────────────┐
|
||
│ Level 2: Django │ → forms_auth.py
|
||
│ Form validation │ → clean_first_name(), clean_last_name()
|
||
└─────────────────────┘
|
||
↓ (to_api_payload)
|
||
┌─────────────────────┐
|
||
│ Level 3: DRF API │ → serializers.py
|
||
│ Serializer check │ → validate_first_name(), validate_last_name()
|
||
└─────────────────────┘
|
||
↓
|
||
Database
|
||
```
|
||
|
||
Каждый уровень независим и может отклонить некорректные данные.
|