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:
72
cleanup_media.py
Normal file
72
cleanup_media.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script to cleanup old photo files with collision suffixes.
|
||||
Deletes files like: original_b374WLW.jpg, large_lmCnBYn.webp etc.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Determine media directory
|
||||
media_dir = Path(__file__).parent / 'myproject' / 'media'
|
||||
|
||||
if not media_dir.exists():
|
||||
print(f"ERROR: media directory not found: {media_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Cleaning old photo files in: {media_dir}")
|
||||
print("=" * 60)
|
||||
|
||||
deleted_count = 0
|
||||
errors = []
|
||||
|
||||
# Walk through all files in media
|
||||
for root, dirs, files in os.walk(str(media_dir)):
|
||||
for filename in files:
|
||||
# Look for files with suffix (pattern: name_XXXXX.extension)
|
||||
# where XXXXX is a random suffix added by Django on collision
|
||||
parts = filename.rsplit('.', 1) # Split name and extension
|
||||
|
||||
if len(parts) != 2:
|
||||
continue
|
||||
|
||||
name, ext = parts
|
||||
|
||||
# Check if there's a suffix (8 chars after last underscore)
|
||||
# Django adds suffixes like: _b374WLW, _lmCnBYn etc.
|
||||
# Also match patterns like testovyi_17613999927705342_original
|
||||
if '_' in name:
|
||||
# Get the last part after underscore
|
||||
parts_by_underscore = name.split('_')
|
||||
last_part = parts_by_underscore[-1]
|
||||
|
||||
# Check for collision suffix (8 alphanumeric chars)
|
||||
# or timestamp-like suffix (14+ digits)
|
||||
is_collision_suffix = (len(last_part) == 8 and last_part.isalnum())
|
||||
is_timestamp_suffix = (len(last_part) >= 14 and last_part.isdigit())
|
||||
|
||||
if is_collision_suffix or is_timestamp_suffix:
|
||||
file_path = os.path.join(root, filename)
|
||||
rel_path = os.path.relpath(file_path, str(media_dir))
|
||||
|
||||
try:
|
||||
os.remove(file_path)
|
||||
deleted_count += 1
|
||||
print(f"[OK] Deleted: {rel_path}")
|
||||
except Exception as e:
|
||||
errors.append(f"[FAIL] Error deleting {rel_path}: {str(e)}")
|
||||
print(f"[FAIL] Error deleting {rel_path}: {str(e)}")
|
||||
|
||||
print("=" * 60)
|
||||
print(f"\nResults:")
|
||||
print(f" [OK] Successfully deleted: {deleted_count} files")
|
||||
|
||||
if errors:
|
||||
print(f" [FAIL] Deletion errors: {len(errors)}")
|
||||
for error in errors:
|
||||
print(f" {error}")
|
||||
else:
|
||||
print(f" [OK] No errors")
|
||||
|
||||
print("\n[DONE] Cleanup completed!")
|
||||
Reference in New Issue
Block a user