mod: django-filer настройка (07) размещение файлов
This commit is contained in:
@@ -6,7 +6,7 @@ from django.apps import AppConfig
|
|||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
|
|
||||||
from lpon_site.settings import THUMBNAIL_WEBP_QUALITY
|
from lpon_site.settings import DEBUG, THUMBNAIL_WEBP_QUALITY
|
||||||
|
|
||||||
# Получаем логгер для текущего модуля
|
# Получаем логгер для текущего модуля
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -28,17 +28,24 @@ class CustomFilerConfig(AppConfig):
|
|||||||
name = 'filer'
|
name = 'filer'
|
||||||
verbose_name = 'Медиафайлы'
|
verbose_name = 'Медиафайлы'
|
||||||
|
|
||||||
@staticmethod
|
# ========================================================================
|
||||||
def generate_upload_path_flr(instance, filename):
|
# Конфигурация Django-Filer, которая читается во время выполнения
|
||||||
from filer.utils.generate_filename import randomized
|
# ========================================================================
|
||||||
base_path = randomized(instance, filename)
|
FILER_ENABLE_PERMISSIONS = DEBUG
|
||||||
return f'flr/{base_path}'
|
FILER_MAX_UPLOAD_SIZE = 100 * 1024 * 1024
|
||||||
|
FILER_WHITELIST_FOR_PATH_ACCESS = (
|
||||||
@staticmethod
|
'.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp',
|
||||||
def generate_upload_path_flrm(instance, filename):
|
'.doc', '.docx', '.pdf', '.txt', '.xls', '.xlsx', '.csv',
|
||||||
from filer.utils.generate_filename import randomized
|
)
|
||||||
base_path = randomized(instance, filename)
|
MIME_TYPE_WHITELIST = (
|
||||||
return f'flrm/{base_path}'
|
'image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp',
|
||||||
|
'application/pdf', 'application/msword',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'text/plain', 'application/vnd.ms-excel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'text/csv',
|
||||||
|
)
|
||||||
|
FILE_VALIDATORS = {}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _convert_to_webp_if_needed(name: str, content):
|
def _convert_to_webp_if_needed(name: str, content):
|
||||||
@@ -52,7 +59,7 @@ class CustomFilerConfig(AppConfig):
|
|||||||
buffer = BytesIO()
|
buffer = BytesIO()
|
||||||
img.save(buffer, format="WEBP", quality=THUMBNAIL_WEBP_QUALITY)
|
img.save(buffer, format="WEBP", quality=THUMBNAIL_WEBP_QUALITY)
|
||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
new_name = name.rsplit(original_ext, 1)[0] + ".webp"
|
new_name = os.path.splitext(name)[0] + ".webp"
|
||||||
logger.info(f"Successfully converted '{name}' to '{new_name}' (WebP).")
|
logger.info(f"Successfully converted '{name}' to '{new_name}' (WebP).")
|
||||||
return ContentFile(buffer.read()), new_name, True
|
return ContentFile(buffer.read()), new_name, True
|
||||||
except Exception:
|
except Exception:
|
||||||
@@ -80,11 +87,8 @@ class CustomFilerConfig(AppConfig):
|
|||||||
new_content.seek(0)
|
new_content.seek(0)
|
||||||
self_instance.instance._file_size = len(file_bytes)
|
self_instance.instance._file_size = len(file_bytes)
|
||||||
self_instance.instance.sha1 = hashlib.sha1(file_bytes).hexdigest()
|
self_instance.instance.sha1 = hashlib.sha1(file_bytes).hexdigest()
|
||||||
|
|
||||||
return original_save(self_instance, new_name, new_content, save)
|
return original_save(self_instance, new_name, new_content, save)
|
||||||
|
|
||||||
MultiStorageFieldFile.save = patched_save
|
MultiStorageFieldFile.save = patched_save
|
||||||
logger.info("MultiStorageFieldFile.save() patched successfully.")
|
logger.info("MultiStorageFieldFile.save() patched successfully.")
|
||||||
|
|
||||||
# Создаем псевдонимы на уровне модуля для функций, чтобы их мог найти Django
|
|
||||||
generate_upload_path_flr = CustomFilerConfig.generate_upload_path_flr
|
|
||||||
generate_upload_path_flrm = CustomFilerConfig.generate_upload_path_flrm
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
# Django-filer и его зависимости
|
# Django-filer и его зависимости
|
||||||
# Порядок важен! polymorphic должен быть ДО filer, easy_thumbnails тоже ДО filer
|
# Порядок важен! polymorphic должен быть ДО filer, easy_thumbnails тоже ДО filer
|
||||||
'polymorphic',
|
# 'polymorphic',
|
||||||
'easy_thumbnails',
|
'easy_thumbnails',
|
||||||
# 'filer',
|
# 'filer',
|
||||||
# Кастомная надстройка над filer для переопределения verbose_name (и других настроек)
|
# Кастомная надстройка над filer для переопределения verbose_name (и других настроек)
|
||||||
@@ -161,82 +161,56 @@ STATICFILES_DIRS = [PUBLIC_DIR.joinpath('static')]
|
|||||||
STATIC_ROOT = PUBLIC_DIR.joinpath('staticfiles')
|
STATIC_ROOT = PUBLIC_DIR.joinpath('staticfiles')
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Django-Filer Configuration - WebP Conversion Storage
|
# Django-Filer & Easy-Thumbnails Configuration
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Настройка хранилища filer для автоматического преобразования изображений в WebP
|
|
||||||
# ВАЖНО: эта конфигурация должна быть в settings.py (не в class attribute),
|
|
||||||
# т.к. Django-filer загружает её ДО инициализации app configs
|
|
||||||
# ВАЖНО: location должна быть равна MEDIA_ROOT, иначе Django не сможет
|
|
||||||
# сгенерировать правильные URL для файлов (URL генерируется как MEDIA_URL + relative_path)
|
|
||||||
#
|
|
||||||
# Структура папок:
|
|
||||||
# public/media/
|
|
||||||
# ├── flr/ <- основные загруженные файлы (картинки)
|
|
||||||
# ├── flrm/ <- миниатюры (thumbnails)
|
|
||||||
# ├── filer_public/ <- старая структура (больше не используется)
|
|
||||||
# └── filer_public_thumbnails/ <- старая структура (больше не используется)
|
|
||||||
FILER_STORAGES = {
|
FILER_STORAGES = {
|
||||||
'public': {
|
'public': {
|
||||||
'main': {
|
'main': {
|
||||||
# Используем стандартное хранилище Django. Логика конвертации в apps.py
|
'ENGINE': 'filer.storage.PublicFileSystemStorage',
|
||||||
'ENGINE': 'django.core.files.storage.FileSystemStorage',
|
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'location': str(MEDIA_ROOT),
|
'location': MEDIA_ROOT / 'flr',
|
||||||
|
'base_url': MEDIA_URL + 'flr/',
|
||||||
},
|
},
|
||||||
# UPLOAD_TO функция добавляет 'flr/' префикс для более компактных путей в шаблонах
|
'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
|
||||||
'UPLOAD_TO': 'frontend.apps.generate_upload_path_flr',
|
|
||||||
'UPLOAD_TO_PREFIX': '',
|
'UPLOAD_TO_PREFIX': '',
|
||||||
},
|
},
|
||||||
'thumbnails': {
|
'thumbnails': {
|
||||||
'ENGINE': 'django.core.files.storage.FileSystemStorage',
|
'ENGINE': 'filer.storage.PublicFileSystemStorage',
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'location': str(MEDIA_ROOT),
|
'location': MEDIA_ROOT / 'flrm',
|
||||||
},
|
'base_url': MEDIA_URL + 'flrm/',
|
||||||
# Миниатюры идят в папку flrm через UPLOAD_TO функцию
|
# 'location': os.path.join(MEDIA_ROOT, 'flrm'),
|
||||||
'UPLOAD_TO': 'frontend.apps.generate_upload_path_flrm',
|
# 'base_url': os.path.join(MEDIA_URL, 'flrm/'),
|
||||||
'THUMBNAIL_OPTIONS': {
|
|
||||||
'base_dir': 'flrm',
|
|
||||||
},
|
},
|
||||||
|
# 'UPLOAD_TO': 'filer.utils.generate_filename.randomized',
|
||||||
|
# 'UPLOAD_TO_PREFIX': '_',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# Easy-Thumbnails Configuration - WebP Generation
|
|
||||||
# ============================================================================
|
|
||||||
# Настройка генерирования миниатюр в формате WebP вместо JPEG/PNG
|
|
||||||
THUMBNAIL_PRESERVE_FORMAT = False # Не сохранять оригинальный формат для миниатюр
|
|
||||||
THUMBNAIL_FORMAT = 'WEBP' # Конвертировать все миниатюры в WebP
|
|
||||||
THUMBNAIL_QUALITY = 80 # Качество WebP (достаточно 75-85 для миниатюр)
|
|
||||||
# Кастомная настройка для встроенного конвертора загружаемых файлов в WebP (см. apps.py)
|
|
||||||
THUMBNAIL_WEBP_QUALITY = 80 # Качество для WebP
|
|
||||||
|
|
||||||
FILER_ENABLE_PERMISSIONS = DEBUG
|
THUMBNAIL_PRESERVE_FORMAT = False
|
||||||
FILER_WHITELIST_FOR_PATH_ACCESS = (
|
THUMBNAIL_FORMAT = 'WEBP'
|
||||||
'.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp',
|
|
||||||
'.doc', '.docx', '.pdf', '.txt', '.xls', '.xlsx', '.csv',
|
|
||||||
)
|
|
||||||
FILER_MAX_UPLOAD_SIZE = 100 * 1024 * 1024
|
|
||||||
MIME_TYPE_WHITELIST = (
|
|
||||||
'image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/webp',
|
|
||||||
'application/pdf', 'application/msword',
|
|
||||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
||||||
'text/plain', 'application/vnd.ms-excel',
|
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
||||||
'text/csv',
|
|
||||||
)
|
|
||||||
THUMBNAIL_ENGINE = 'easy_thumbnails.engines.pil_engine.PilEngine'
|
|
||||||
THUMBNAIL_DEBUG = DEBUG
|
THUMBNAIL_DEBUG = DEBUG
|
||||||
FILE_VALIDATORS = {}
|
THUMBNAIL_WEBP_QUALITY = 80
|
||||||
|
THUMBNAIL_ENGINE = 'easy_thumbnails.engines.pil_engine.PilEngine'
|
||||||
# Размеры миниатюр для разных использований
|
|
||||||
THUMBNAIL_ALIASES = {
|
THUMBNAIL_ALIASES = {
|
||||||
'': {
|
'': {
|
||||||
# Для админ-интерфейса
|
|
||||||
'admin_thumbnail': {'size': (64, 64), 'crop': True},
|
'admin_thumbnail': {'size': (64, 64), 'crop': True},
|
||||||
# Для фронтенда
|
|
||||||
'small': {'size': (256, 256), 'crop': True},
|
'small': {'size': (256, 256), 'crop': True},
|
||||||
'medium': {'size': (512, 512), 'crop': True},
|
'medium': {'size': (512, 512), 'crop': True},
|
||||||
'large': {'size': (1024, 1024), 'crop': 'smart'},
|
'large': {'size': (1024, 1024), 'crop': 'smart'},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
FILER_UPLOADER_MAX_FILES = 3
|
||||||
|
FILER_UPLOADER_MAX_FILE_SIZE = 100 * 1024 * 1024
|
||||||
|
FILER_MAX_IMAGE_PIXELS = 4096 * 4096
|
||||||
|
|
||||||
|
# Настройки для "умной" обрезки изобращений
|
||||||
|
THUMBNAIL_PROCESSORS = (
|
||||||
|
'easy_thumbnails.processors.colorspace',
|
||||||
|
'easy_thumbnails.processors.autocrop',
|
||||||
|
#'easy_thumbnails.processors.scale_and_crop',
|
||||||
|
'filer.thumbnail_processors.scale_and_crop_with_subject_location',
|
||||||
|
'easy_thumbnails.processors.filters',
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user