django-imagekit thumbnail serializer for Django Rest Framework + extra

Viewed 267

guys. I spent some time figuring out how can I use django-imagekit with DRF without defining ImageSpecField fields in model (a large number of thumbnail types make model dirty).

from collections import OrderedDict
from rest_framework import serializers
from imagekit.cachefiles import ImageCacheFile


class ThumbnailField(serializers.ImageField):
    def __init__(self, spec, **kwargs):
        self.spec = spec
        super().__init__(**kwargs)

    def to_representation(self, original_image):
        if not original_image:
            return None

        cached = ImageCacheFile(self.spec(original_image))
        cached.generate()
        return super().to_representation(cached)


class ImageKitField(serializers.ImageField):
    def __init__(self, **kwargs):
        self.specs = kwargs.pop('specs', {})
        self.full = kwargs.pop('full', False)
        super().__init__(**kwargs)

    def to_representation(self, original_image):
        if not original_image:
            return None

        result = OrderedDict()

        for field_name, spec in self.specs.items():
            cached = ImageCacheFile(spec(original_image))
            cached.generate()
            result[field_name] = super().to_representation(cached)

        if self.full:
            result['full'] = super().to_representation(original_image)

        return result

Using

ThumbnailField return just image thumb url. You can also use source and other ImageField params like so:

class UserSerializer(serializers.ModelSerializer):
    thumb = ThumbnailField(spec=UserThumbnailSpec, source='image')

Result:

{
    "thumb": "http://example.com/.../thumb.jpg"
}

ImageKitField is extra field which group multiple thumbnail dimensions together. full is optional flag that include original image to result dict.

class UserSerializer(serializers.ModelSerializer):
    image = ThumbnailField(specs={
        'small': SmallThumbnailSpec,
        'large': LargeThumbnailSpec,
    }, full=True)

Result:

{
    "image": {
        "small": "http://example.com/.../small.jpg",
        "large": "http://example.com/.../large.jpg",
        "full": "http://example.com/.../full.jpg",
    }
}

Enjoy!

0 Answers
Related