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>
This commit is contained in:
2025-11-02 12:51:26 +03:00
parent d92045c4c4
commit d15e7d9414
4 changed files with 300 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
# Исправление бага: Подмена фотографий при загрузке
## Проблема
При загрузке новой фотографии к товару она подменялась другой уже существующей фотографией. Пользователь загружал одно фото, но в БД и на сайте появлялось совершенно другое.
## Причина
**Корневая причина**: Коллизия имен файлов при сохранении фотографий.
### Как это происходило:
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()` добавлена проверка и удаление старого файла ПЕРЕД сохранением нового:
```python
# ВАЖНО: Удаляем старый файл если он существует, чтобы избежать коллизий имен
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 и т.д.) которое лучше справляется с коллизиями имен