""" Визуальные компоненты для отображения качества фотографий в Django админке. Модулю используется для форматирования вывода уровней качества фото с цветами, иконками и подсказками. """ from django.conf import settings from django.utils.html import format_html def get_quality_color(quality_level): """ Получить цвет Bootstrap для уровня качества. Args: quality_level (str): Уровень качества Returns: str: CSS цвет (success/info/warning/danger) """ labels = getattr(settings, 'IMAGE_QUALITY_LABELS', {}) info = labels.get(quality_level, {}) return info.get('color', 'secondary') def get_quality_label(quality_level): """ Получить человеко-читаемое название уровня качества. Args: quality_level (str): Уровень качества Returns: str: Название (например, "Отлично") """ labels = getattr(settings, 'IMAGE_QUALITY_LABELS', {}) info = labels.get(quality_level, {}) return info.get('label', 'Неизвестно') def get_quality_icon(quality_level): """ Получить иконку для уровня качества. Args: quality_level (str): Уровень качества Returns: str: Иконка (✓, ◐, ⚠, ✗) """ labels = getattr(settings, 'IMAGE_QUALITY_LABELS', {}) info = labels.get(quality_level, {}) return info.get('icon', '?') def format_quality_badge(quality_level, show_icon=True): """ Форматирует уровень качества в виде цветного бэджа Bootstrap. Пример вывода: [🟢 Отлично] или [🔴 Плохо] Args: quality_level (str): Уровень качества (excellent/good/acceptable/poor/very_poor) show_icon (bool): Показывать ли иконку Returns: str: HTML с отформатированным бэджем """ labels = getattr(settings, 'IMAGE_QUALITY_LABELS', {}) info = labels.get(quality_level, {}) label_text = info.get('label', 'Неизвестно') color = info.get('color', 'secondary') icon = info.get('icon', '?') description = info.get('description', '') # Формируем текст бэджа if show_icon: badge_text = f"{icon} {label_text}" else: badge_text = label_text # Выбираем CSS класс Bootstrap badge_class = info.get('badge_class', 'badge-secondary') # Создаем HTML с tooltip при наведении html = format_html( '{}', badge_class, description, badge_text ) return html def format_quality_badge_with_size(quality_level, width=None, height=None): """ Форматирует качество с указанием размеров изображения. Пример: "🟢 Отлично (2150×2150px)" Args: quality_level (str): Уровень качества width (int): Ширина изображения (опционально) height (int): Высота изображения (опционально) Returns: str: HTML с бэджем и размерами """ label_text = get_quality_label(quality_level) icon = get_quality_icon(quality_level) color = get_quality_color(quality_level) size_text = "" if width and height: size_text = f" ({width}×{height}px)" labels = getattr(settings, 'IMAGE_QUALITY_LABELS', {}) info = labels.get(quality_level, {}) badge_class = info.get('badge_class', 'badge-secondary') html = format_html( '{} {}{}', badge_class, icon, label_text, size_text ) return html def format_quality_display(quality_level, width=None, height=None, warning=False): """ Полное отображение качества с индикатором warning. Args: quality_level (str): Уровень качества width (int): Ширина изображения (опционально) height (int): Высота изображения (опционально) warning (bool): Требует ли обновления Returns: str: HTML с полной информацией о качестве """ badge = format_quality_badge_with_size(quality_level, width, height) if warning: # Добавляем индикатор warning warning_indicator = format_html( ' ⚠️ Требует обновления' ) return format_html('{} {}', badge, warning_indicator) return badge def format_photo_quality_column(obj, show_size=True): """ Для использования в list_display - отображает качество фотографии объекта. Пример использования: def photo_quality(self, obj): return format_photo_quality_column(obj) photo_quality.short_description = 'Качество фото' Args: obj: Product, ProductKit или ProductCategory объект show_size (bool): Показывать ли размеры Returns: str: HTML с качеством первого фото """ first_photo = obj.photos.first() if not first_photo: return format_html('Нет фото') if show_size: return format_quality_display( first_photo.quality_level, width=first_photo.width if hasattr(first_photo, 'width') else None, height=first_photo.height if hasattr(first_photo, 'height') else None, warning=first_photo.quality_warning ) else: return format_quality_badge(first_photo.quality_level) def format_photo_inline_quality(photo_obj): """ Для использования в inline таблицах - отображает качество фото в строке. Args: photo_obj: ProductPhoto, ProductKitPhoto или ProductCategoryPhoto объект Returns: str: HTML с качеством фото """ if not photo_obj.pk: # Новый объект еще не сохранён return format_html('Сохраните фото') return format_quality_display( photo_obj.quality_level, width=photo_obj.width if hasattr(photo_obj, 'width') else None, height=photo_obj.height if hasattr(photo_obj, 'height') else None, warning=photo_obj.quality_warning ) def format_photo_preview_with_quality(photo_obj, max_width=250, max_height=250): """ Превью фотографии с индикатором качества под ней. Args: photo_obj: ProductPhoto, ProductKitPhoto или ProductCategoryPhoto объект max_width (int): Максимальная ширина превью max_height (int): Максимальная высота превью Returns: str: HTML с фото и индикатором качества """ if not photo_obj.image: return format_html('Нет изображения') quality_display = format_quality_badge(photo_obj.quality_level) html = format_html( '
' '' '
{}
' '
', photo_obj.get_large_url() if hasattr(photo_obj, 'get_large_url') else photo_obj.image.url, max_width, max_height, quality_display ) return html def get_quality_filter_display(value): """ Получить описание фильтра для качества фото. Args: value (str): Значение фильтра (excellent/good/acceptable/poor/very_poor/warning/no_warning) Returns: str: Описание для отображения """ filter_descriptions = { 'excellent': '🟢 Отлично', 'good': '🟡 Хорошо', 'acceptable': '🟠 Приемлемо', 'poor': '🔴 Плохо', 'very_poor': '🔴 Очень плохо', 'warning': '⚠️ Требует обновления', 'no_warning': '✓ Готово к выгрузке', } return filter_descriptions.get(value, value)