From 6df929fff842c495bd2130eb2c8b2fb631758104 Mon Sep 17 00:00:00 2001 From: Gabriel von Heijne Date: Tue, 7 Apr 2015 16:09:02 +0200 Subject: [PATCH] [#1384] Add custom to_native method to Base64ImageField Add Base64ImageField.to_native() to include the full path to the image in any API use and add the option of requesting a thumbnail as part of an API get request. See docstring and comments in to_native() for more details. --- akvo/rest/fields.py | 49 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/akvo/rest/fields.py b/akvo/rest/fields.py index 2d9996ad5c..5ca9895f51 100644 --- a/akvo/rest/fields.py +++ b/akvo/rest/fields.py @@ -7,7 +7,6 @@ import base64 import imghdr -import os import six import uuid @@ -16,8 +15,7 @@ from rest_framework import serializers from rest_framework.fields import ImageField - -from akvo import settings +from sorl.thumbnail import get_thumbnail class NonNullCharField(serializers.CharField): @@ -69,10 +67,49 @@ def from_native(self, base64_data): return super(Base64ImageField, self).from_native(data) def to_native(self, value): - """ Return the full path to the image, including the MEDIA_URL part """ - value = super(Base64ImageField, self).to_native(value) - return os.path.join(settings.MEDIA_URL, value) + :param value: A Base64ImageField object + :return: The full path to the image. If the request includes a special query string param a thumbnail is + generated and returned along with the original + + If the querystring part of the request includes the query param "image_thumb_name" a thumbnail is generated, + provided that at least one of "width" and "height" parameters is also supplied. The image_thumb_name value is + used as the key for the thumbnail in the dict returned. + If a thumbnail is included a dict with two members is returned: + { + 'original': '/full/path/to/original/image.png', + '': '/full/path/to/thumbnail/image.png' + } + This dict will be converted as appropriate to JSON or XML + + NOTE: This special functionality works best when there is only one image field in a model. If there are more, + things will still work (I think), but all thumbs returned will have the same dimensions + """ + ORIGINAL_KEY = u'original' + if value: + # get the full path of original image + image_url = value.url + image_thumb_name = self.context['request'].GET.get('image_thumb_name') + # do we have a request for a thumbnail? + # also make sure the thumb isn't named "original"! + if image_thumb_name and image_thumb_name.lower() != ORIGINAL_KEY: + width = self.context['request'].GET.get('width') + height = self.context['request'].GET.get('height') + # set thumb size according to what data we got + if width and height: + thumb = get_thumbnail(value, '{}x{}'.format(width, height), quality=99) + elif width: + thumb = get_thumbnail(value, '{}'.format(width), quality=99) + elif height: + thumb = get_thumbnail(value, 'x{}'.format(height), quality=99) + else: + # bail if we get neither width nor heigth + return image_url + # populate dict with original and thumb paths + image_dict = {ORIGINAL_KEY: image_url} + image_dict[image_thumb_name] = thumb.url + return image_dict + return image_url def get_file_extension(self, filename, decoded_file): extension = imghdr.what(filename, decoded_file)