How can I pass an image to a template in Django?

Question:

Suppose that the corresponding function in views.py looks like

from PIL import Image
def get_img(request, img_source)
    base_image = Image.open(os.getcwd() + '/deskprod/media/img/'+ img_source + ".png")
    #Some editing of base_image done with PIL that prevents image from being directly loaded in html
    return render_to_response('get_img.html', {
        'base_image': base_image},
        context_instance=RequestContext(request))

How can I then display base_image in the get_img.html template?

Asked By: Everyone_Else

||

Answers:

I think you must save image (write it to temp file) in static directory of project and in template use static command and image file name to display it.

You should process the image, save it on local disk and then send a path to it or more like the media url which will correspond to that image as context to html template. You need to configure your django server to serve static and media files to do that and configure serving those files in production environment as well. Read more here https://docs.djangoproject.com/en/1.9/howto/static-files/

However it should be possible to create dynamic image and serve with django in the fly with PIL if you can’t or really do not want to save it locally. It will be sth like at the and of you code you should add.

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

Check also more info http://effbot.org/zone/django-pil.htm, it may work, although I didn’t test it.

Answered By: Kamil Zajac

settings.py

   'DIRS': [os.path.join(BASE_DIR, 'templates')], # add this line in TEMPLATES
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media/images')
    MEDIA_URL = '/media/images/'

add templates and media/images directory where manage.py is stored.

urls.py

urlpatterns = [

                  url('polls/', views.get_img, name="polls"),


              ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

views.py

from django.conf import settings

def get_img(request):
    path = settings.MEDIA_ROOT
    img_list = os.listdir(path + "/")
    print(img_list[0])
    base_image = "http://127.0.0.1:8000/media/images/" + img_list[0]
    content = {"base_image": base_image}
    return render(request, 'get_img.html', content)

get_img.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>drop_down</title>
</head>
<body>

  {{base_image}}
  <img src="{{base_image}}" style="width: 20%; height: 20%;" alt="{{base_image}}">

</body>
</html>
Answered By: shivam sharma

You can pass image as base64 bytes to Django template, and then use it in html:

view.py

from PIL import Image
from io import BytesIO
import base64
    
    
# Convert Image to Base64
def image_to_base64(image):
    buff = BytesIO()
    image.save(buff, format="PNG")
    img_str = base64.b64encode(buff.getvalue())
    img_str = img_str.decode("utf-8")  # convert to str and cut b'' chars
    return img_str

def home(request):
    image = Image.open('some_image.png')
    image64 = image_to_base64(image)
    return render(request, 'index.html', {'image64': image64})

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <img src="data:image/png;base64,{{image64}}">
</body>
</html>

It will works for JPG too – need to change all PNG mentions to JPG in .py/.html

Answered By: Sinba