Сериализатор изображений DRF с вложенными миниатюрами
Я пишу проект django, в котором у меня есть следующие модели в моем приложении media_app:
class Image(File):
"""
Image model class, through which client will get images stored on AWS S3.
"""
# ... (not needed in serializer fields)
class Thumbnail(File):
"""
Related model for Image, that contains thumbnails of Image.
"""
parent = models.ForeignKey(
Image,
on_delete=models.CASCADE,
related_name='thumbnails',
)
resolution = models.CharField(
_('resolution'),
max_length=11,
validators=[resolution_validator],
)
# ...
Класс File - это базовый класс модели для медиафайлов в моем проекте. Он содержит mime_type, origina_file_name, size
, и т.д.
Мой вопрос заключается в том, как я могу написать сериализатор для Image, который будет иметь следующую структуру:
{
"2775f83e-1608-4135-91d3-f357484df3b1": {
"full_size": "http://localhost:8000/api/media/2775f83e-1608-4135-91d3-f357484df3b1/",
"358x227": "http://localhost:8000/api/media/8809a43d-c387-4a8e-9c84-8419c406ecd8/",
"190x121": "http://localhost:8000/api/media/cb32967e-a576-44ee-b636-6e3a65ec93ba/"
}
}
Где "2775f...df3b1"
- pk изображения, "full_size"
- его собственный get url (модель имеет метод/свойство api_url
, которое генерирует endpoint url для получения представления медиафайла), а другие поля ("358x227"
и "190x121"
) являются url-ами связанных миниатюр (ключи взяты из полей разрешения в Thumbnail). Такая структура не является обычной для DRF, поэтому я не нашел решения в документации...
Сериализатор будет использоваться в других ModelSerializers. Image содержит внешние ключи к другим моделям, которым нужны медиа файлы (я не использую Django Content Type, только nullable OneToOnes), и в api_url будет обычный ModelSerializer для Image, поэтому мне нужна вышеуказанная структура только в связанных моделях, таких как Article.
Я проверил некоторые другие вопросы на stackOverflow, и нашел .to_representation
метод ModelSerializer. Для получения необходимого представления (вышеприведенная структура), и я просто переписал этот метод. В результате получился следующий код:
class RelatedImageSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
thumbnails = instance.thumbnails.all()
image_api_urls = {"full_size": instance.api_url}
for thumbnail in thumbnails:
image_api_urls[thumbnail.resolution] = thumbnail.api_url
return {str(instance.pk): image_api_urls}
class Meta:
model = Image
fields = ('id',) # will not be used, because to_representation method was overwrite
Все работает нормально, но я не проверял все случаи, только 2 конечные точки моего API.