If I render a static image in the .html template it works. But if I provide the static markup string as dictionary value to the template (the context), it will not work. It seems to be something to do with string formatting and not allowing me to use {% %} the way I need to. I have tried:
1. .format()
2. escaping the percent characters
3. raw strings
4. concatenation
5. autoescape
6. | safe
and a number of other things
Basically, I am constructing a multi-line string in view.py with '''{% %}''', and then rendering a template with this string as the context. Python 2.
UPDATE
Simple non-working example:
view.py
def index(request):
image_insert = ''
images = ['image1.jpg', 'image2.jpg', 'image3.jpg']
for image in images:
image_insert += '<img src="{}">'.format(image)
context = {'insert': image_insert}
template = loader.get_template('index.html')
return HttpResponse(template.render(context, request))
index.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>Basic HTML File</title>
</head>
<body>
First Image
<img src={% static "image.jpg" %}>
Second Image <!-- does not work -->
{{ image_insert | safe }}
</body>
</html>
Page Source:
<!DOCTYPE html>
<html>
<head>
<title>Basic HTML File</title>
</head>
<body>
<img src=/static/mqdefault.jpg>
Second Image
<img src="image1.jpg"><img src="image2.jpg"><img src="image3.jpg">
</body>
</html>
Obviously, there is a difference. This is Django 1.11 btw if it makes a difference.
You can also achieve this by passing img source from the view as follow:
views.py
from django.contrib.staticfiles.templatetags.staticfiles import static
def index(request):
context = {'image_src': static("image.jpg")}
template = loader.get_template('index.html')
return HttpResponse(template.render(context, request))
index.html
<!DOCTYPE html>
<html>
<head>
<title>Basic HTML File</title>
</head>
<body>
<img src="{{ image_src }}">
</body>
</html>
UPDATE: Multiple Images
You can generate markup with multiple images and pass it in the context as seen in the views.py:
views.py
from django.contrib.staticfiles.templatetags.staticfiles import static
def index(request):
images = [static('image1.jpg'), static('image2.jpg'), static('image3.jpg')]
images_html = "".join([
"<img src={image}>".format(image=image)
for image in images
])
context = {'images_html': images_html)}
template = loader.get_template('index.html')
return HttpResponse(template.render(context, request))
Now, your updated index.html will be:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Basic HTML File</title>
</head>
<body>
{{ images_html|safe }}
</body>
</html>
Hope it helps.
working code:
def index(request):
context = {'image_insert': "image.jpg"}
template = loader.get_template('index.html')
return HttpResponse(template.render(context, request))
index.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>Basic HTML File</title>
</head>
<body>
First Image
<img src="{% static "image.jpg" %}">
Second Image <!-- does not work -->
<img src="{% static image_insert %}">
</body>
</html>
Related
I'm starting with Django and I working with HTML and I would like to convert to pdf.
I have this view which I get the data registered in my DB by id:
def contrato(request, id):
return render(request,'contrato\contrato.html', {'asociado': get_queryset(id)})
This renders me the following html, it is something simple:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CPS</title>
</head>
<body>
<h1>Contrato de Prestación de Servicios</h1>
<div>
<ul>
{% for dato in asociado %}
<li>Función/Título: {{ dato.job_title }}</li>
<li>nombre completo: {{ dato.first_name }} {{ dato.last_name }}</li>
<li>Email: {{ dato.email }}</li>
<li>RFC: {{ dato.rfc }}</li>
<li>CURP: {{ dato.curp }}</li>
<li>Clabe: {{ dato.interbank_key }}</li>
<li>País: {{ dato.country }}</li>
<li>Status: {{ dato.status }}</li>
<li>Creado: {{dato.created}}</li>
{% endfor %}
</ul>
</div>
</body>
</html>
How can I convert this html to pdf with the registered data to download. I have only achieved an empty pdf (without the data) or only with the H1 header.
I will appreciate any help!
You can use wkhtml2pdf, which will need a HTML document and will generate a pdf file,then return to the generated file to the user, something like this
def contrato(request, id):
HTML = render(request,'contrato\contrato.html', {'asociado': get_queryset(id)}).content
f = open("/tmp/report.html","w")
f.write(HTML)
f.close()
import subprocess
subprocess.run("wkhtml2pdf /tmp/report.html /tmp/report.pdf")
return FileStream(open("/tmp/report.pdf","rb"), as_attachment=True)
Doing this without an external library is going to be pretty complicated and involves transpiling the HTML to PDF.
Instead, you'll probably want to use a library like xhtml2pdf.
First pip install xhtml2pdf. Then update your controller function:
from xhtml2pdf import pisa
# ...
def contrato(request, id):
if request.path_info.split('.')[-1] == "pdf"
return render_pdf(request, 'contrato/contrato.html', {'asociado': get_queryset(id)})
return render(request, 'contrato\contrato.html', {'asociado': get_queryset(id)})
def render_pdf(request, template_path, context)
filename = f'{template_path.split('.')[0]}.pdf'
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="{filename}"'
template = get_template(template_path)
html = template.render(context)
pisa_status = pisa.CreatePDF(html, dest=response)
if pisa_status.err:
return HttpResponse(f'We had some errors <pre>{html}</pre>')
return response
For more advanced use cases, you'll probably want to refer to the documentation linked above.
See Problem Here
I want to loop over a directory of static images in Django. The images are being looped over correctly, but something is wrong with my <img src /> syntax. I've tried many variations on {{ flag }} but can't get anything to work. Can anybody advise?
In settings.py I created the following STATIC_ROOT object:
STATIC_ROOT = '/Users/TheUnforecastedStorm/Desktop/Code_projects/Portfolio_Site/portfolio_site/entrance/static'
In views.py I joined this file path to my image directory and placed the list of images in the context dictionary. I then included this dictionary in my response:
import os
from django.conf import settings
from django.shortcuts import render
# Create your views here.
def index(request):
# Create a dictionary
context = {}
# Join images directory to index.html view
flags = os.listdir(os.path.join(settings.STATIC_ROOT, "entrance/images/"))
context['flags'] = flags
# Return response
return render(request, "entrance/index.html", context)
I then looped over these images in my template:
<!DOCTYPE html>
{% load static %}
<html>
<head>
<link rel="stylesheet" href="{% static 'entrance/entrance.css' %}">
<script src="{% static 'entrance/entrance.js' %}" type="text/javascript"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
{% for flag in flags %}
<img src="{{ flag }}" alt="problem" />
{% endfor %}
</body>
</html>
#Mark1 Working off my comments from above, I haven't been able to find anything to confirm it but it seems like the {% static %} template tag can only take one extra argument to make a path, so here is something you can try.
In your view:
def index(request):
# Create a dictionary
context = {}
# Join images directory to index.html view
flags = os.listdir(os.path.join(settings.STATIC_ROOT, "entrance/images/"))
# ADD IN THIS LINE HERE
flags = ['entrance/images/'+fl for fl in flags]
context['flags'] = flags
# Return response
return render(request, "entrance/index.html", context)
The line I added in will add "entrance/images/" to the start of all the file names in the directory you are searching.
Then in your template
{% for flag in flags %}
<img src="{% static flag %}" alt="problem" />
{% endfor %}
Let me know if this works.
view.py
map = folium.Map(location=[df['latitude'].mean(),
df['longitude'].mean()],tiles="cartodbpositron",zoom_start=12)
map.save("map.html")
context = {'my_map': map}
return render(request, 'my_map.html', context)
my_map.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ my_map }}
</body>
browser result:
folium.folium.Map object at 0x7f49d85662b0
im not sure how to approach getting the html/js to work on the browser after the user has submitted their input via the previous html form...
I have seemed to look everywhere and there are a lot of similar problems with solutions but I could not get any to work!
Thanks!
This response is here to increase the google coverage for others who, like me, also experienced this problem when trying to render a Folium map within a Django template.
Your Code
Please see the comments inside each code block for how to render the map as expected.
views.py
map = folium.Map(location=[df['latitude'].mean(),
df['longitude'].mean()],tiles="cartodbpositron",zoom_start=12)
map.save("map.html")
# {'my_map': map} will output the object, which is what you are seeing
# to rectify this we need to turn it into an iframe which
# the template can then render.
context = {'my_map': map} # change to {'my_map': map._repr_html_()}
return render(request, 'my_map.html', context)
Template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
# after making the change in our views.py this will return the html but
# the template will not render it as expected because it is being escaped.
# You must declare it 'safe' before it will be rendered correctly.
{{ my_map }} # change to {{ my_map | safe }}
</body>
For more information see the Folium doc page here or this SO post.
Hope that helps.
Map objects have a render method which render its html representation.
You can try directly:
<body>
{{ my_map.render }}
</body>
Or you can use the Map.render method to implement a custom inclusion tag, that way you can pass arguments to the render method. See this for reading more about inclusion and custom tags.
# The template tag.
for django.template import Library
register = Library()
#register.inclusion_tag
def render_map(map_object, **kwargs):
return map_object.render(**kwargs)
In your template:
<body>
{% render_map my_map some_arg1=arg1 some_arg2=arg2 %}
</body>
Am Unable to sent the temp_k variable from my views to index.html. I have made a request from weather API and trying to pass it to my html.
Please suggest how we are supposed to send the variable from views to template.
views.py
from django.template.loader import render_to_string
import requests
from django.shortcuts import render
from django.http import HttpResponse
def hello(request):
my_dict = {'insert_me': "From andu.py"}
return render(request, 'mywebapp/index.html', context=my_dict)
def temperature(request):
#zip=requests.form['zip']ss
r=requests.get('http://samples.openweathermap.org/data/2.5/weather?zip=94040,us&appid=b6907d289e10d714a6e88b30761fae22')
json_object=r.json()
my_dict1={'temp_k' :json_object['main']['temp']}
return render(request,'mywebapp/index.html', context=my_dict1)
index.html
<!DOCTYPE html>
{% load staticfiles%}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hey</title>
<link rel="stylesheet" href={% static "cs/style.css" %}/>
</head>
<body>
<h1>This is the Header</h1>
<img src="{% static "images/youownme.jpeg" %}" atl="Uh Oh">
<h2> Temperature:{{temp_k}}</h2>
</body>
</html>
I have tried your code and it works fine so you may want to check if you are rendering the right HTML files maybe, i've changed your code to make sure it's working and it is
my_dict1={'temp_k' :json_object['wind']['speed']}
sorry but I cant write a comment yet!
Use render like this :
return render(request,'mywebapp/index.html',{'context':my_dict})
I'm trying to get a file that's in my media directory to appear on an HTML template. I'm using the "Tango with Django" book as a tutorial.
Here is my settings.py:
MEDIA_DIR = os.path.join(BASE_DIR, 'media')
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'
Here is views.py:
def about(request):
return render(request, 'rango/about.html', )
And my about.html template:
<!DOCTYPE html>
{%load staticfiles%}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>About</title>
</head>
<body>
<h1>This is the about page</h1>
<img src="{{MEDIA_URL}} {{cat.jpg}}"
alt="cats are funny"/>
<div>
Index
</div>
</body>
</html>
I know I must be missing something very obvious, but can't figure it out for the life of me!
The {{MEDIA_URL}} tag is deprecated. Use the {% get_media_prefix %} tag, instead.
<img src="{% get_media_prefix %}cat.jpg" alt="cats are funny"/>
From the documentation:
Similar to the get_static_prefix, get_media_prefix populates a template variable with the media prefix MEDIA_URL.
When rendered, that src attribute will be equivalent to /media/cat.jpg. You may want to consider using STATIC_ROOT in your settings.py, instead, along with the {% static %} tag:
<img src="{% static 'cat.jpg' %}" alt="cats are funny"/>
I think the problems should be errors in format.
Try the following two revisions:
1. in your render(), change "return render(request, 'rango/about.html', )" to "return render(request, 'rango/about.html') by deleting the last comma;
2. in your template file about.html, change .