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:
90
BUG_FIX_PHOTO_COLLISION.md
Normal file
90
BUG_FIX_PHOTO_COLLISION.md
Normal 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 и т.д.) которое лучше справляется с коллизиями имен
|
||||
Reference in New Issue
Block a user