diff --git a/myproject/products/templates/products/product_form.html b/myproject/products/templates/products/product_form.html index 46014ea..126040e 100644 --- a/myproject/products/templates/products/product_form.html +++ b/myproject/products/templates/products/product_form.html @@ -182,11 +182,23 @@ {% if object and product_photos %}
-
Текущие фотографии ({{ photos_count }})
-
+
+
Текущие фотографии ({{ photos_count }})
+ +
+
{% for photo in product_photos %} -
-
+
+
+ +
+ +
+
+ + + {% endif %} diff --git a/myproject/products/urls.py b/myproject/products/urls.py index c120ad1..e7f2d91 100644 --- a/myproject/products/urls.py +++ b/myproject/products/urls.py @@ -24,6 +24,7 @@ urlpatterns = [ path('product/photo//set-main/', views.product_photo_set_main, name='product-photo-set-main'), path('product/photo//move-up/', views.product_photo_move_up, name='product-photo-move-up'), path('product/photo//move-down/', views.product_photo_move_down, name='product-photo-move-down'), + path('product/photos/delete-bulk/', views.product_photos_delete_bulk, name='product-photos-delete-bulk'), # CRUD URLs for ProductKit (комплекты/букеты) path('kit/create/', views.ProductKitCreateView.as_view(), name='productkit-create'), diff --git a/myproject/products/views/__init__.py b/myproject/products/views/__init__.py index 25d1285..a49dcbe 100644 --- a/myproject/products/views/__init__.py +++ b/myproject/products/views/__init__.py @@ -12,6 +12,7 @@ from .photo_management import ( product_photo_set_main, product_photo_move_up, product_photo_move_down, + product_photos_delete_bulk, ) # Управление фотографиями (ProductKit) @@ -105,6 +106,7 @@ __all__ = [ 'product_photo_set_main', 'product_photo_move_up', 'product_photo_move_down', + 'product_photos_delete_bulk', # Управление фотографиями ProductKit 'productkit_photo_delete', diff --git a/myproject/products/views/photo_management.py b/myproject/products/views/photo_management.py index a468e53..1b88e5c 100644 --- a/myproject/products/views/photo_management.py +++ b/myproject/products/views/photo_management.py @@ -2,8 +2,13 @@ Универсальные функции для управления фотографиями товаров, комплектов и категорий. Устраняет дублирование кода для операций: delete, set_main, move_up, move_down. """ +import json from django.shortcuts import get_object_or_404, redirect from django.contrib import messages +from django.http import JsonResponse +from django.views.decorators.http import require_http_methods +from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import PermissionRequiredMixin from ..models import ProductPhoto, ProductKitPhoto, ProductCategoryPhoto @@ -308,3 +313,71 @@ def category_photo_move_down(request, pk): parent_attr='category', permission='products.change_productcategory' ) + + +# ==================================== +# AJAX Endpoints для массового удаления +# ==================================== + +@require_http_methods(["POST"]) +@login_required +def product_photos_delete_bulk(request): + """ + AJAX endpoint для массового удаления фотографий товара. + + Ожидает JSON: {photo_ids: [1, 2, 3]} + Возвращает JSON: {success: true, deleted: 3} или {success: false, error: "..."} + """ + # Проверка прав доступа + if not request.user.has_perm('products.change_product'): + return JsonResponse({ + 'success': False, + 'error': 'У вас нет прав для удаления фотографий' + }, status=403) + + try: + # Получаем список photo_ids из JSON тела запроса + data = json.loads(request.body) + photo_ids = data.get('photo_ids', []) + + if not photo_ids or not isinstance(photo_ids, list): + return JsonResponse({ + 'success': False, + 'error': 'Неверный формат: требуется список photo_ids' + }, status=400) + + # Удаляем фотографии + deleted_count = 0 + for photo_id in photo_ids: + try: + photo = ProductPhoto.objects.get(pk=photo_id) + photo.delete() # Это вызовет ImageProcessor.delete_all_versions() + deleted_count += 1 + except ProductPhoto.DoesNotExist: + # Если фото не найдена, просто пропускаем + continue + except Exception as e: + # Логируем ошибку но продолжаем удаление остальных + import logging + logger = logging.getLogger(__name__) + logger.error(f"Error deleting photo {photo_id}: {str(e)}", exc_info=True) + continue + + return JsonResponse({ + 'success': True, + 'deleted': deleted_count + }) + + except json.JSONDecodeError: + return JsonResponse({ + 'success': False, + 'error': 'Неверный JSON формат' + }, status=400) + except Exception as e: + import logging + logger = logging.getLogger(__name__) + logger.error(f"Bulk photo deletion error: {str(e)}", exc_info=True) + return JsonResponse({ + 'success': False, + 'error': f'Ошибка сервера: {str(e)}' + }, status=500)