Files
octopus/BUG_FIX_PHOTO_COLLISION.md
Andrey Smakotin d15e7d9414 fix: Исправить подмену фотографий при загрузке (коллизия имен файлов)
Проблема была в том, что при сохранении фотографии Django обнаруживал коллизию имен
и добавлял суффикс (например, original_b374WLW.jpg), но в БД сохранялся путь БЕЗ суффикса.
Это приводило к тому, что фотография не находилась и отображалась другая.

Решение:
- В ImageProcessor добавлена проверка и удаление старого файла перед сохранением нового
- Это гарантирует что путь в БД совпадает с реальным файлом на диске
- Удалены все старые файлы с суффиксами коллизии из media папки
- Создана management команда cleanup_photo_media для периодической очистки

Файлы:
- myproject/products/utils/image_processor.py: добавлена очистка старого файла
- myproject/products/management/commands/cleanup_photo_media.py: команда для очистки
- cleanup_media.py: скрипт для ручной очистки (уже запущен)
- BUG_FIX_PHOTO_COLLISION.md: подробный отчет о проблеме и решении

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 12:51:26 +03:00

5.6 KiB
Raw Blame History

Исправление бага: Подмена фотографий при загрузке

Проблема

При загрузке новой фотографии к товару она подменялась другой уже существующей фотографией. Пользователь загружал одно фото, но в БД и на сайте появлялось совершенно другое.

Причина

Корневая причина: Коллизия имен файлов при сохранении фотографий.

Как это происходило:

  1. Система сохраняет фотографии по структуре: products/{entity_id}/{photo_id}/{размер}.{расширение}

    • Пример: products/2/7/original.jpg, products/2/7/large.webp, и т.д.
  2. Когда нужно перезаписать фотографию (при обновлении), Django обнаруживает что файл уже существует

  3. Вместо замены, Django добавляет суффикс коллизии к имени файла:

    • Ожидается: products/2/3/original.jpg
    • Реально сохраняется: products/2/3/original_LxC9yjS.jpgс суффиксом
  4. ПРОБЛЕМА: В БД сохраняется путь БЕЗ суффикса (products/2/3/original.jpg), но физически файл находится в другом месте (products/2/3/original_LxC9yjS.jpg)

  5. Когда шаблон запрашивает {{ photo.image.url }}, Django ищет файл products/2/3/original.jpg, не находит его, и возвращает путь по умолчанию или другую доступную фотографию.

Решение

Шаг 1: Обновлен image_processor.py

В методе _save_image_version() добавлена проверка и удаление старого файла ПЕРЕД сохранением нового:

# ВАЖНО: Удаляем старый файл если он существует, чтобы избежать коллизий имен
if default_storage.exists(file_path):
    try:
        default_storage.delete(file_path)
        logger.info(f"Deleted old file: {file_path}")
    except Exception as e:
        logger.warning(f"Could not delete old file {file_path}: {str(e)}")

Это гарантирует что:

  • Старый файл удаляется перед сохранением нового
  • Django не встречает коллизию имен
  • Путь в БД совпадает с реальным расположением файла на диске

Шаг 2: Очистка старых данных

Создан и запущен скрипт cleanup_media.py который:

  • Удалил все старые файлы с суффиксами коллизии (original_b374WLW.jpg, large_lmCnBYn.webp и т.д.)
  • Удалил старые файлы из папки products/originals/ (старая схема хранения)

Результат: Успешно удалено 6 устаревших файлов

Файлы, измененные

  1. myproject/products/utils/image_processor.py

    • Добавлена проверка и удаление старого файла перед сохранением нового
    • Добавлено логирование коллизий имен
  2. myproject/products/management/commands/cleanup_photo_media.py

    • Создана management команда для очистки старых файлов (опционально)
  3. cleanup_media.py (в корне проекта)

    • Создан скрипт для ручной очистки старых данных

Как проверить исправление

  1. Откройте товар с ID 2 (или любой другой товар)
  2. Попробуйте загрузить новое фото
  3. При сохранении фото должно правильно отобразиться
  4. В папке myproject/media/products/ не должно быть файлов с суффиксами вроде _b374WLW, _LxC9yjS и т.д.

Технические детали

  • Файлы с коллизией: Django использует функцию storage.save() которая добавляет суффикс если файл существует
  • Суффикс коллизии: 8 случайных буквенно-цифровых символов вроде _b374WLW
  • Старые файлы: Имели паттерн {название}_{timestamp}_original.jpg (из старой системы)

Результаты

✓ Исправлено ошибочное сохранение путей в БД ✓ Удалены все старые файлы с коллизией имен ✓ Добавлена проверка при сохранении новых фотографий ✓ Добавлено логирование для отладки будущих проблем с коллизиями

Рекомендации

  1. Периодически проверяйте папку myproject/media/ на наличие файлов с суффиксами
  2. Можно добавить периодическую очистку через Celery или cron
  3. В продакшене рекомендуется использовать облачное хранилище (S3 и т.д.) которое лучше справляется с коллизиями имен