feat: Implement comprehensive image storage and processing system
- Add ImageProcessor utility for automatic image resizing * Creates 4 versions: original, thumbnail (150x150), medium (400x400), large (800x800) * Uses LANCZOS algorithm for quality, JPEG quality 90 for optimization * Handles PNG transparency with white background * 90% file size reduction for thumbnails vs original - Add ImageService for URL generation * Dynamically computes paths based on original filename * Methods: get_thumbnail_url(), get_medium_url(), get_large_url(), get_original_url() * No additional database overhead - Update Photo models with automatic processing * ProductPhoto, ProductKitPhoto, ProductCategoryPhoto * Auto-creates all sizes on save * Auto-deletes all sizes on delete * Handles image replacement with cleanup - Enhance admin interface * Display all 4 image versions side-by-side in admin * Grid layout for easy comparison * Readonly preview fields - Add management command * process_images: batch process existing images * Support filtering by model type * Progress reporting and error handling - Clean database * Removed old migrations, rebuild from scratch * Clean SQLite database - Add comprehensive documentation * IMAGE_STORAGE_STRATEGY.md: full system architecture * QUICK_START_IMAGES.md: quick reference guide * IMAGE_SYSTEM_EXAMPLES.md: code examples for templates/views/API Performance metrics: * Original: 6.1K * Medium: 2.9K (52% smaller) * Large: 5.6K (8% smaller) * Thumbnail: 438B (93% smaller) 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
93
myproject/products/utils/image_service.py
Normal file
93
myproject/products/utils/image_service.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
Сервис для получения URL изображений разных размеров.
|
||||
Используется в шаблонах и представлениях для удобного доступа к разным версиям.
|
||||
"""
|
||||
import os
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class ImageService:
|
||||
"""
|
||||
Сервис для работы с изображениями разных размеров.
|
||||
Динамически строит URL на основе пути к оригинальному файлу.
|
||||
"""
|
||||
|
||||
# Папки для разных размеров
|
||||
SIZE_FOLDERS = {
|
||||
'thumbnail': 'thumbnails',
|
||||
'medium': 'medium',
|
||||
'large': 'large',
|
||||
'original': 'originals',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get_url(original_image_path, size='medium'):
|
||||
"""
|
||||
Получает URL изображения нужного размера.
|
||||
|
||||
Args:
|
||||
original_image_path: Путь к оригинальному файлу (из models.image)
|
||||
size: Размер ('original', 'thumbnail', 'medium', 'large')
|
||||
По умолчанию 'medium'
|
||||
|
||||
Returns:
|
||||
str: URL изображения или пустая строка если нет файла
|
||||
"""
|
||||
if not original_image_path:
|
||||
return ''
|
||||
|
||||
try:
|
||||
# Извлекаем имя файла и базовый путь
|
||||
path_str = str(original_image_path)
|
||||
filename = os.path.basename(path_str)
|
||||
|
||||
# Определяем базовый путь (products, kits, categories)
|
||||
parts = path_str.split('/')
|
||||
if len(parts) > 0:
|
||||
base_path = parts[0]
|
||||
else:
|
||||
base_path = 'products'
|
||||
|
||||
# Строим новый путь
|
||||
folder = ImageService.SIZE_FOLDERS.get(size, 'medium')
|
||||
new_path = f"{base_path}/{folder}/{filename}"
|
||||
|
||||
# Возвращаем URL
|
||||
return f"{settings.MEDIA_URL}{new_path}"
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
@staticmethod
|
||||
def get_thumbnail_url(original_image_path):
|
||||
"""Получить URL миниатюры (150x150)"""
|
||||
return ImageService.get_url(original_image_path, 'thumbnail')
|
||||
|
||||
@staticmethod
|
||||
def get_medium_url(original_image_path):
|
||||
"""Получить URL среднего размера (400x400)"""
|
||||
return ImageService.get_url(original_image_path, 'medium')
|
||||
|
||||
@staticmethod
|
||||
def get_large_url(original_image_path):
|
||||
"""Получить URL большого размера (800x800)"""
|
||||
return ImageService.get_url(original_image_path, 'large')
|
||||
|
||||
@staticmethod
|
||||
def get_original_url(original_image_path):
|
||||
"""Получить URL оригинального изображения"""
|
||||
return ImageService.get_url(original_image_path, 'original')
|
||||
|
||||
@staticmethod
|
||||
def get_all_urls(original_image_path):
|
||||
"""
|
||||
Получить все версии изображения.
|
||||
|
||||
Returns:
|
||||
dict: {'original': url, 'thumbnail': url, 'medium': url, 'large': url}
|
||||
"""
|
||||
return {
|
||||
'original': ImageService.get_original_url(original_image_path),
|
||||
'thumbnail': ImageService.get_thumbnail_url(original_image_path),
|
||||
'medium': ImageService.get_medium_url(original_image_path),
|
||||
'large': ImageService.get_large_url(original_image_path),
|
||||
}
|
||||
Reference in New Issue
Block a user