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?
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.
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>
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
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?
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.
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>
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