Добавлено быстрое создание тегов на странице списка

API функционал:
- Создан endpoint /api/tags/create/ для AJAX создания тегов
- Валидация: пустое имя, длина, уникальность (регистронезависимо)
- Автоматическая генерация slug через модель
- Возврат JSON с данными созданного тега

UI функционал на странице списка тегов:
- Панель быстрого создания с крупным полем ввода
- Автофокус на поле при загрузке страницы
- Создание тега по нажатию Enter или клику на кнопку
- Индикатор загрузки (спиннер) во время создания
- Блокировка поля/кнопки во время запроса
- Автоматическая перезагрузка страницы после создания
- Возврат фокуса в поле при ошибке
- Красивые alert-сообщения об успехе/ошибке
- CSRF защита

Workflow: ввёл название → Enter → тег создан → фокус снова в поле → можно вводить следующий

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-11 23:26:40 +03:00
parent 1a0360f8c0
commit 1daee88cbd
4 changed files with 193 additions and 1 deletions

View File

@@ -620,3 +620,94 @@ def create_temporary_kit_api(request):
'success': False,
'error': f'Ошибка при создании комплекта: {str(e)}'
}, status=500)
def create_tag_api(request):
"""
AJAX endpoint для быстрого создания тега из списка тегов.
Принимает JSON:
{
"name": "Новый тег"
}
Возвращает JSON:
{
"success": true,
"tag": {
"id": 1,
"name": "Новый тег",
"slug": "novyj-teg",
"is_active": true,
"products_count": 0,
"kits_count": 0
}
}
Или при ошибке:
{
"success": false,
"error": "Описание ошибки"
}
"""
if request.method != 'POST':
return JsonResponse({
'success': False,
'error': 'Метод не поддерживается'
}, status=405)
try:
import json
from ..models import ProductTag
data = json.loads(request.body)
name = data.get('name', '').strip()
# Валидация
if not name:
return JsonResponse({
'success': False,
'error': 'Название тега не может быть пустым'
}, status=400)
if len(name) > 100:
return JsonResponse({
'success': False,
'error': 'Название тега слишком длинное (максимум 100 символов)'
}, status=400)
# Проверка уникальности (регистронезависимо)
if ProductTag.objects.filter(name__iexact=name).exists():
return JsonResponse({
'success': False,
'error': f'Тег "{name}" уже существует'
}, status=400)
# Создание тега (slug будет сгенерирован автоматически в модели)
tag = ProductTag.objects.create(
name=name,
is_active=True
)
return JsonResponse({
'success': True,
'tag': {
'id': tag.id,
'name': tag.name,
'slug': tag.slug,
'is_active': tag.is_active,
'products_count': 0,
'kits_count': 0
}
})
except json.JSONDecodeError:
return JsonResponse({
'success': False,
'error': 'Некорректный JSON'
}, status=400)
except Exception as e:
return JsonResponse({
'success': False,
'error': f'Ошибка при создании тега: {str(e)}'
}, status=500)