django xhtml2pdf not getting image - python

I am trying to render html to pdf, it really works great ! only there is an issue and that is the template getting image:
I am using python xhtml2pdf library for pdf render
this is my method for render pdf:
def render_pdf(template_src, context_dict):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("utf-8")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return HttpResponse('Unable to process the request, We had some errors<pre>%s</pre>' % escape(html))
and this is my views.py below:
def test_view(request):
context = {
'test': 'a test string'
}
return render_pdf('test.html', context)
and this my test.html
{% load static %}
<p>hello test </p>
<img src="{% static 'ok.jpg' %}">
It gets image if i render with django default render method But the image not getting when i render for pdf.
I heard of this solution with link_callback method with this documatin: https://xhtml2pdf.readthedocs.io/en/latest/usage.html
I am not getting where to include this or how can i achive this.
Can anyone help me in this case?

I suggest modifying your html template, and use the absolute / relative path (directory path in your hard drive) of the image file instead of using {% static %} tag. static tag is only good for rendering the HTMl, but pisa cant read the image from that.
I have this code from a project that generates a PDF from html, and my images are done like this:
<img src="{{ STATIC_ROOT }}/report/logo.png" >
where STATIC_ROOT is a variable passed from render context.

This worked for me if it is still relevant.
My static folder is in my root directory.
{% load static %}

Related

How to properly show image stored from a remote file server to a django HTML template?

I have trouble displaying images stored in a file server to the django template.
File server link is \11234.123.123.123\dashboard.jpg (just a sample).
It seems like the img src url is being added by the django localhost url prefix to the file server path as follows: http://127.0.0.1:8000/dashboard/\\11234.123.123.123\dashboard.jpg
In django template, the img tag is written as:
<img class="imgView" src="{{dashboard_image}}" alt="Dashboard画面.jpg"></img>
My views.py just sends the image file server URL as text (with value of \11234.123.123.123\dashboard.jpg) to be displayed as image in the HTML page as the django template.
def dashboard(request):
dashboard_image_url = '\\11234.123.123.123\dashboard.jpg' #TODO temporary, just sample
context = {'dashboard_image': dashboard_image_url}
return render(request, 'dashboard.html', context)
But, the image does not show properly as follows.
Please help, thank you!
In your template instead of:
<img class="imgView" src="{{dashboard_image}}" alt="Dashboard画面.jpg"></img>
DO this:
<img class="imgView" src="{{dashboard_image.url}}" alt="Dashboard画面.jpg"></img>
<img class='img-responsive' src="{{ MEDIA_URL }}{{ item.image.url }}" />
or
<img class='img-responsive' src="{{ item.image.url }}" />
and in main urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

How do I reference a local media file in a Django template

I have set up my media root, media url etc. so the file will show up when I call
http://127.0.0.1:8000/media/something/somewhere/my_pdf.pdf
Now I want to show the same file within a template (i.e. the PDF in an object or embed tag plus some other stuff. I pass the path to the file (i.e. everything after 'media' in the view context, something like:
def test_doc(request):`
p = r'something/somewhere/my_pdf.pdf'`
return render(request, 'documents/test.html', {'pdf':p})
So what do I have to put in my template? I tried
<object data="{{ MEDIA_URL }}{{ pdf }}">something</object>
and many many variations thereof. What am I doing wrong?
I tested your approach and I believe I was able to reproduce your issue.
PDF was displayed in browser from address: http://127.0.0.1:8000/myapp/media/myapp/my_pdf.pdf
PDF not displayed when loaded into an object with <object data="{{ MEDIA_URL }}{{ pdf }}"></object> in template
PDF not displayed when loaded into an object with <object data="{% get_media_prefix %}{{ pdf }}"> in template
There are two problems occurring simultaneously.
Django's default project settings enable clickjacking protection using X-Frame-Options. This does not prevent loading the media files with a direct request, but does so when you try to load media into an object. Firefox Inspector shows an error message: The loading of “http://127.0.0.1:8000/myapp/media/myapp/my_pdf.pdf” in a frame is denied by “X-Frame-Options“ directive set to “DENY“.
Django's documentation tells to use #xframe_options_exempt decorator for the view. It did not help in my tests. Disabling clickjacking protection by commenting out 'django.middleware.clickjacking.XFrameOptionsMiddleware' in settings.py allowed me to display PDF in an object with <object data="media/myapp/my_pdf.pdf"> in the template.
Both {{ MEDIA_URL }}{{ pdf }} and {% get_media_prefix %}{{ pdf }} tags in the template lead to loading the PDF from the disk with path "/media/myapp/my_pdf.pdf". Note the extra "/" in the beginning. You can prevent this by defining p = 'media/myapp/my_pdf.pdf' in the view and using <object data="{{ pdf }}"> in the template. Not very elegant, but works when clickjacking middleware is disabled.
Since you have set up MEDIA_ROOT and MEDIA_URL, you should use the {% get_media_prefix %} template tag:
{% load static %}
<object data="{% get_media_prefix %}{{ pdf }}">something</object>
EDIT:
If you are running in development mode (DEBUG = True), you also need to change your urls.py to serve media files:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ...
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
According to your code it doesn't look like MEDIA_URL is defined in your views context.
from django.conf import settings
def test_doc(request):`
p = r'something/somewhere/my_pdf.pdf'`
return render(request, 'documents/test.html', {'pdf':p, 'MEDIA_URL': settings.MEDIA_URL})
To complete answer of drec4s that fixes Django side stuff, you will need to add a markup like this one on your template :
<embed type="application/pdf" src= "{% get_media_prefix %}{{ pdf }}" width= "500" height= "375">

Serve images with Django

I am sending my images from my web server Django like follows :
localhost:8000/media/images/foo.png
My question is am I sending the images is the correct way? I think it is not necessary to send the server since I am the only one who serves the photographs. Any ideas, something like this media/images/foo.png.
In order that in the img tag of HTML this is a relative path and not a link.
For serving images in Django,
First make sure that you have your MEDIA_ROOT and MEDIA_URL defined inside the settings.py file.
Now let's say you have a model, models.py
class SomeModel(models.Model):
image = models.ImageField(upload_to = 'your_directory_inside_media')
#Rest of the fields
Next inside your views,
model_object = SomeModel.objects.get(...) #get an instance of model which has an ImageField
context = {'image' : model_object.image }
html = render(request , 'some_html.html' , context)
And finally inside your HTML,
{% load static %}
<img src="{% get_media_prefix %}{{ image.image }}">
Hope this helps. Thanks.

How to view dynamically generated svg image in template using <img> html tag (Django)?

I have a url linked to a view that returns an image (successfully).
I am trying to use this url as a value of <img> tag src attribute inside template html file.
urls.py
url(r'^$',views.index,name='index'),
url(r'^image/(?P<graph_name>[a-zA-z]+)$', views.dynamic_image, name='dynamic-image'),
)
views.py
def dynamic_image(request, graph_name):
image=functionToCreateImage(graph_name)
return HttpResponse(image, content_type="image/svg+xml")
def index(request):
template = loader.get_template('graphs/index.html')
context = RequestContext(request, {
'gene_links_graph':reverse('dynamic-image', args=['gene_links_graph'])})
return HttpResponse(template.render(context))
index.html
...
<a href = "{{ gene_links_graph }}">
<img scr="{{ gene_links_graph }}" alt="img1">
</a>
...
The image renders on a new page via link, but does not appear on index.html page. How to fix that?
upd rendered html page source
<a href = "/graphs/image/gene_links_graph/">
<img scr="/graphs/image/gene_links_graph/" alt="img1">
</a>
There is a similar thread, but it didn't work in my case
django: serve dynamic (reportlab) png to template
Why is the generated HTML <img scr=""> instead of <img src="">? Could that be your problem?

How to read images from directory, assemble them in <img src="">, and have flask return image?

I have a directory full of images. In one of my templates, I want to display these images
GET template:
render_template("registration.html", images=images)
in template: (using image/{{image}} because url_for doesn't accept variables)
{% for image in images %}
<input class="avatar" type = "radio" name = "avatar" value = "{{image}}"/><img src = "image/{{image}}"/>
{% endfor %}
and in app.py
#app.route('/images/<image>')
def images(image):
return send_file('public/assets/thumbs'+image, mimetype='image/jpg')
(public/assets/thumbs is the directory images reside in) however, this fails completely. Is there any tricks or hacks I can use to make this work?
I don't know if it could help you neither if the method i'll describe is good practice but to display images from directory (using send_from_directory in my view as described below by Andrew Allbright) in templates I was using :
{% for image in images %}
<img src="{{url_for('static', filename='image/')}}{{image}}"></img>
{% endfor %}
I remember I took inspiration from this SO post: Create dynamic URLs in Flask with url_for() (second answer) that indicates you can pass argument to url_for() in your templates.
Solution: send_from_directory()
#app.route("/image/<image>", methods=["GET"])
def image(image):
return send_from_directory(app.static_folder, 'assets/thumbs/' + image, mimetype='image/jpg')

Categories

Resources