# api/v1/documents/fields.py """ Кастомные serializer fields для работы с django-filer. """ from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from django.core.files.uploadedfile import UploadedFile from filer.models import File as FilerFile import logging logger = logging.getLogger(__name__) @extend_schema_field(OpenApiTypes.URI) class FilerFileField(serializers.Field): """ Serializer field для работы с django-filer FilerFileField. При чтении (GET): - Возвращает URL файла из filer.File.url При записи (POST/PUT/PATCH): - Принимает UploadedFile - Создает filer.File объект - Возвращает filer.File instance для присвоения в модель """ def to_representation(self, value): """ Преобразует filer.File в URL для API response. Args: value: filer.File instance или None Returns: str: Полный URL файла или None """ if value is None: return None if isinstance(value, FilerFile): if not value.url: return None # Получаем request из контекста для построения абсолютного URL request = self.context.get("request") if request: return request.build_absolute_uri(value.url) # Fallback: возвращаем относительный URL return value.url return None def to_internal_value(self, data): """ Преобразует UploadedFile в filer.File instance. Args: data: UploadedFile из request Returns: FilerFile: Созданный filer.File объект Raises: serializers.ValidationError: При ошибках валидации """ if data is None: return None if not isinstance(data, UploadedFile): raise serializers.ValidationError("Ожидается файл для загрузки.") # Получаем пользователя из контекста request = self.context.get("request") owner = getattr(request, "user", None) if request else None try: # Создаем filer.File объект # is_public=True делает файл доступным без авторизации filer_file = FilerFile.objects.create( file=data, original_filename=data.name, name=data.name, owner=owner, is_public=True, # Делаем файл публичным для доступа с frontend ) logger.info( "Document file created", extra={ "event": "document.file.created", "file_id": filer_file.id, "owner_id": owner.id if owner else None, "is_public": True, "size_bytes": data.size, }, ) return filer_file except Exception as e: logger.exception( "Document file creation failed", extra={ "event": "document.file.creation_failed", "owner_id": owner.id if owner else None, "size_bytes": data.size, "error_type": type(e).__name__, }, ) raise serializers.ValidationError(f"Ошибка при создании файла: {str(e)}")