109 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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(
f"[FilerFileField] Created filer.File id={filer_file.id} "
f"name={data.name} owner={
owner.id if owner else None
} is_public=True"
)
return filer_file
except Exception as e:
logger.error(
f"[FilerFileField] Error creating filer.File: {e}",
exc_info=True,
)
raise serializers.ValidationError(
f"Ошибка при создании файла: {str(e)}"
)