Files
octopus/myproject/products/views/utils.py
Andrey Smakotin f7d1851418 fix: Сохранять первые 10 фото, остальные отклонять с уведомлением
Изменено поведение handle_photos():
- Если загружено больше 10 фото, сохраняются первые 10
- Остальные отклоняются с warning сообщением
- Товар теперь ВСЕГДА создается (даже если больше 10 фото)

Это позволяет пользователю загрузить 11+ фото,
но система обработает только первые 10 и уведомит об этом.

🤖 Generated with Claude Code
2025-11-15 11:20:51 +03:00

80 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Утилиты для работы с фотографиями товаров, комплектов и категорий.
"""
import os
from django.db import models
def validate_photo(photo):
"""
Валидация загружаемого фото.
Возвращает (True, None) если валидно, или (False, error_message) если ошибка.
"""
max_size = 5 * 1024 * 1024 # 5MB
allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp']
if photo.size > max_size:
return False, f'Размер файла {photo.name} превышает 5MB.'
ext = os.path.splitext(photo.name)[1].lower()
if ext not in allowed_extensions:
return False, f'Формат файла {ext} не поддерживается. Разрешены: {", ".join(allowed_extensions)}'
return True, None
def handle_photos(request, parent_obj, photo_model, parent_field_name):
"""
Универсальная обработка загружаемых фотографий.
Args:
request: HTTP request с FILES
parent_obj: Родительский объект (Product, ProductKit или ProductCategory)
photo_model: Модель фотографии (ProductPhoto, ProductKitPhoto, ProductCategoryPhoto)
parent_field_name: Имя поля связи в модели фото ('product', 'kit', 'category')
Returns:
Список сообщений об ошибках (пустой список если все ок).
"""
errors = []
warnings = []
photos = request.FILES.getlist('photos')
if not photos:
return errors
# МАКСИМУМ 10 ФОТО - сохраняем первые 10, остальные отклоняем
MAX_PHOTOS = 10
if len(photos) > MAX_PHOTOS:
warnings.append(f'Загружено {len(photos)} фото, но обработано только первые {MAX_PHOTOS}. '
f'Максимум {MAX_PHOTOS} фото на товар.')
photos = photos[:MAX_PHOTOS]
# Получаем максимальный order для этого родительского объекта
filter_kwargs = {parent_field_name: parent_obj}
max_order = photo_model.objects.filter(**filter_kwargs).aggregate(
models.Max('order')
)['order__max']
# Если фото нет, начинаем с 0, иначе с max_order + 1
next_order = 0 if max_order is None else max_order + 1
# Валидация и сохранение фото
for photo in photos:
is_valid, error_msg = validate_photo(photo)
if not is_valid:
errors.append(error_msg)
else:
# Создаем фото с правильной связью
create_kwargs = {
parent_field_name: parent_obj,
'image': photo,
'order': next_order
}
photo_model.objects.create(**create_kwargs)
next_order += 1
# Добавляем warnings в errors для отображения пользователю
errors.extend(warnings)
return errors