27

How do I serve a dynamically generated image in Django?

I have an html tag

<html>
...
    <img src="images/dynamic_chart.png" />
...
</html>

linked up to this request handler, which creates an in-memory image

def chart(request):
    img = Image.new("RGB", (300,300), "#FFFFFF")
    data = [(i,randint(100,200)) for i in range(0,300,10)]
    draw = ImageDraw.Draw(img)
    draw.polygon(data, fill="#000000")
    # now what?
    return HttpResponse(output)

I also plan to change the requests to AJAX, and add some sort of caching mechanism, but my understanding is that wouldn't affect this part of the solution.

pufferfish
  • 16,651
  • 15
  • 56
  • 65

4 Answers4

31

I assume you're using PIL (Python Imaging Library). You need to replace your last line with (for example, if you want to serve a PNG image):

response = HttpResponse(mimetype="image/png")
img.save(response, "PNG")
return response

See here for more information.

Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
  • 1
    I'm using PIL for this example but probably going to use other libraries like matplotlib. Should work too though. – pufferfish Jul 02 '09 at 14:38
  • 7
    use content_type instead of mime type if you are using Django 1.10 + – codingrhythm Mar 26 '17 at 23:20
  • Update for python3 from PILLOW import Image from io import BytesIO img = Image.open("some_image.jpg") img_byte_arr = BytesIO() img.save(img_byte_arr, format='PNG') return HttpResponse( img_byte_arr.getvalue(), "image/png" ) – TaeWoo Jul 15 '21 at 08:14
3

I'm relatively new to Django myself. I haven't been able to find anything in Django itself, but I have stumbled upon a project on Google Code that may be of some help to you:

django-dynamic-media-serve

geowa4
  • 40,390
  • 17
  • 88
  • 107
3

I was looking for a solution of the same problem

And for me this simple approach worked fine:

from django.http import FileResponse

def dyn_view(request):

    response = FileResponse(open("image.png","rb"))
    return response
1

Another way is to use BytesIO. BytesIO is like a buffer. So one can save the image (which is fast enough than writing to disk) in that buffer.

from PIL import Image, ImageDraw
import io

def chart(request):
    img = Image.new('RGB', (240, 240), color=(250,160,170))
    draw = ImageDraw.Draw(img)
    draw.text((20, 40), 'some_text')

    buff = io.BytesIO()
    img.save(buff, 'jpeg')
    return HttpResponse(buff.getvalue(), content_type='image/jpeg')
Jayanta
  • 11
  • 2