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!