Corp/docs/completed/MEDIA_STORAGE_REFACTORING.md
lizerk a662642864 docs: добавление документации по рефакторингу
- Добавлен отчет о рефакторинге хранилища медиафайлов
- Добавлено сравнение веток feature/django-filer-documents и develop
- Добавлен аудит frontend документов
- Добавлен отчет об очистке types, cabinets и dashboard
2026-03-06 12:33:18 +03:00

9.1 KiB
Raw Blame History

Рефакторинг структуры хранения медиа-файлов

Дата: 5 марта 2026
Статус: ✅ Завершено

🎯 Цели

Переход от хеш-структуры django-filer к читаемой структуре с организацией по датам.

📁 Было (deprecated)

media/filer_public/
├── 07/28/07286222-01c2-415c-ad2f-fc0ee3eb13f0/    ← Нечитаемая хеш-структура
├── 2a/cd/2acdaf8f-b428-42d6-aaf6-b9b63353e836/
└── ...

Проблемы старой структуры:

  • ❌ Невозможно найти файл вручную
  • ❌ Сложно организовать архивацию
  • ❌ Нет ясности по периодам хранения
  • ❌ Усложняет бэкапы по датам

📁 Стало (new)

media/
├── documents/
│   ├── public/2026/03/05/          ← Публичные документы по дате
│   ├── private/2026/03/05/         ← Приватные документы по дате
│   ├── public_thumbnails/          ← Превью публичных документов
│   └── private_thumbnails/         ← Превью приватных документов
├── avatars/                         ← Аватарки пользователей
├── chat_attachments/2026/03/05/    ← Вложения мессенджера
└── temp/                            ← Временные файлы

Преимущества новой структуры:

  • ✅ Читаемые пути: documents/public/2026/03/05/contract.pdf
  • ✅ Простая архивация: перемещение старых папок (например, 2024/)
  • ✅ Удобные бэкапы: легко выбрать период
  • ✅ Естественная организация: по дате загрузки

🔧 Изменения в коде

1. Django settings.py

Было:

FILER_STORAGES = {
    'public': {
        'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
        'UPLOAD_TO_PREFIX': '%Y/%m',  # Не работало правильно
    }
}

Стало:

FILER_STORAGES = {
    'public': {
        'main': {
            'ENGINE': 'filer.storage.PublicFileSystemStorage',
            'OPTIONS': {
                'location': os.path.join(MEDIA_ROOT, 'documents/public/'),
                'base_url': '/media/documents/public/',
            },
            'UPLOAD_TO': 'filer.utils.generate_filename.by_date',  # ← Ключевое изменение
        },
        'thumbnails': {
            'ENGINE': 'filer.storage.PublicFileSystemStorage',
            'OPTIONS': {
                'location': os.path.join(MEDIA_ROOT, 'documents/public_thumbnails/'),
                'base_url': '/media/documents/public_thumbnails/',
            },
        },
    },
    'private': {
        'main': {
            'ENGINE': 'filer.storage.PrivateFileSystemStorage',
            'OPTIONS': {
                'location': os.path.join(MEDIA_ROOT, 'documents/private/'),
                'base_url': '/smedia/documents/private/',
            },
            'UPLOAD_TO': 'filer.utils.generate_filename.by_date',  # ← Ключевое изменение
        },
        'thumbnails': {
            'ENGINE': 'filer.storage.PrivateFileSystemStorage',
            'OPTIONS': {
                'location': os.path.join(MEDIA_ROOT, 'documents/private_thumbnails/'),
                'base_url': '/smedia/documents/private_thumbnails/',
            },
        },
    },
}

Ключевые изменения:

  • randomized → by_date - функция генерации путей
  • Организация: YYYY/MM/DD/filename.ext
  • Раздельные пути для public/private

2. URL конфигурация (urls.py)

Было:

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Стало:

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Причина: В production статика раздается через Nginx, не Django.

3. .gitignore

Добавлено:

backend/media/*
!backend/media/.gitkeep
!backend/media/*/
!backend/media/*/.gitkeep
!backend/media/*/*/
!backend/media/*/*/.gitkeep

Результат: Git отслеживает структуру папок (через .gitkeep), но игнорирует загруженные файлы.

🧪 Тестирование

Тест создания файла

from django.core.files.base import ContentFile
from filer.models import File

test_content = ContentFile(b"Test document content", name="test_document.txt")
test_file = File.objects.create(
    original_filename="test_document.txt",
    file=test_content
)

print(test_file.file.path)
# Результат: /backend/media/documents/private/2026/03/05/test_document.txt
print(test_file.file.url)
# Результат: /smedia/documents/private/2026/03/05/test_document.txt

Результаты

✅ Путь корректный: documents/private/2026/03/05/test_document.txt
✅ Дата в пути: 2026/03/05 (YYYY/MM/DD)
✅ URL правильный: /smedia/documents/private/2026/03/05/test_document.txt
✅ Django check: 0 ошибок

📋 Management команда

Создана команда для миграции старых файлов:

python manage.py migrate_documents_storage --dry-run  # Предпросмотр
python manage.py migrate_documents_storage            # Выполнить миграцию

Статус миграции:

  • Проверено: 34 записи в БД
  • Физически файлов: 0 (старые файлы уже удалены)
  • Миграция не требуется

Файл: backend/documents/management/commands/migrate_documents_storage.py

📚 Документация

Создана документация со структурой и инструкциями:

  • Файл: backend/media/README.md
  • Разделы:
    • Структура директорий
    • Настройка FILER_STORAGES
    • Инструкции по миграции
    • Безопасность (public vs private)
    • Конфигурация Nginx для production

🧹 Очистка

Удалены устаревшие структуры:

rm -rf backend/media/filer_public/      # Старая хеш-структура
rm -rf backend/media/documents/private/%Y/  # Тестовые папки

До очистки:

  • 47 директорий
  • 10 тестовых файлов в filer_public/

После очистки:

  • 14 директорий (чистая структура)
  • .gitkeep файлы во всех пустых папках

🎯 Итоги

✅ Выполнено

  1. ✅ Настроена структура documents/public/ и documents/private/
  2. ✅ Изменен генератор путей на by_date (YYYY/MM/DD)
  3. ✅ Обновлена конфигурация Django (settings.py)
  4. ✅ Исправлен URL routing для production
  5. ✅ Настроен .gitignore для media/
  6. ✅ Создана management команда миграции
  7. ✅ Написана документация (README.md)
  8. ✅ Протестировано создание файлов
  9. ✅ Удалены старые структуры
  10. ✅ Созданы .gitkeep файлы

📊 Метрики

  • Файлов изменено: 4 (settings.py, urls.py, .gitignore, README.md)
  • Файлов создано: 2 (management команда + отчет)
  • Директорий очищено: 33 (из 47 осталось 14)
  • Ошибок Django check: 0
  • TypeScript ошибок: 0 (не затронуто)

🚀 Готовность к production

  • ✅ Nginx конфигурация описана в README.md
  • ✅ URL routing работает корректно
  • ✅ Безопасность (public/private разделение)
  • ✅ Структура масштабируемая
  • ✅ Бэкапы легко организовать по датам

📌 Следующие шаги (опционально)

  1. Настройка Nginx - для раздачи static/media в production
  2. Автоочистка - удаление старых файлов (например, старше 1 года)
  3. S3 интеграция - для облачного хранения (если требуется масштабирование)
  4. Мониторинг - отслеживание размера media/ директории

🔗 Связанные документы

  • backend/media/README.md - Руководство по структуре
  • backend/documents/management/commands/migrate_documents_storage.py - Команда миграции
  • backend/eusrr_backend/settings.py - Конфигурация FILER_STORAGES