Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django REST API to expose images

I have a django app and I want to expose the model images, such that when I request /image/school_id/400 it will return the image of school with id school_id cropped and resized to a box 400x400 px. Here is what I tried

@api_view(['GET', 'POST'])
def image_view(request,  school_id, size):

    image = School.objects.get(school__pk=school_id).image
    resized_img = image #Handle resizing here

    return Response(resized_img, content_type='*/*')

and all am getting is an error 'utf8' codec can't decode byte 0xff in position 0: invalid start byte

How do i return the image? Am using Django-rest-framework http://www.django-rest-framework.org/api-guide/renderers#advanced-renderer-usage

like image 909
Alexxio Avatar asked Oct 29 '14 00:10

Alexxio


2 Answers

You are trying to return the raw image data and have Django REST Framework render the response. As the response should not be different based on the chosen format, you should be using a raw HttpResponse object.

return HttpResponse(resized_img, content_type="image/png")

Note that the content_type should reflect the content type of the returned response, which should match the content type of the image that is being resized.


The error that you are getting is because the Renderer classes are expecting text-based responses, not image data. Django REST Framework will not apply the custom renderers to HttpResponse classes, only to Django REST Framework Response classes.

like image 149
Kevin Brown-Silva Avatar answered Nov 20 '22 11:11

Kevin Brown-Silva


I know it's a quite old question, but I found solution to this problem. You can use a custom renderer from Django Rest Framework to return image by Response. For example:

class CustomRenderer(renderers.BaseRenderer):
    media_type = 'image/png'
    format = 'png'
    charset = None
    render_style = 'binary'

    def render(self, data, media_type=None, renderer_context=None):
        return data

And in views you have to call this renderer by:

  • Decorator: @renderer_classes((CustomRenderer,))

or

  • Renderer classes: renderer_classes = (CustomRenderer, )

Note. Remember about the semicolon

If you are using decorator like @action you might have problem with call your renderer by decorator. In this case you have to use renderer_classes in @action decorator:

@action(methods=['get'], detail=True, renderer_classes=(CustomRenderer,))
like image 3
strg Avatar answered Nov 20 '22 11:11

strg