Exporting html to pdf using django - django

I am trying to export my html pages into pdf using Pisa library in django, and here is the code that I use to do that:
def fetch_resources(uri, rel):
path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
return path
def write_pdf(template_src, context_dict):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")),dest = result, encoding='UTF-8', link_callback=fetch_resources)
if not pdf.err:
return http.HttpResponse(result.getvalue(), mimetype='application/pdf')
return http.HttpResponse('Sorry, no pdf! %s' % cgi.escape(html))
def article(request):
return write_pdf('Storehouse/ReceiptPrint-v2.html',{'pagesize':'A4'})
But I have two problems when I get the pdf output: first, it does not render my css files and all of my styles are missed in the pdf (my css files are very large, so please don't suggest to have the style in the html file) and second it does not understand the specified unicode (UTF-8), my html pages are in Farsi, but when it turns into pdf, it changes into some meaningless squares.
Any help would be appreciated a lot!

Pisa's converter uses the ReportLab Toolkit, which has a difficult time rendering Farsi and other Arabic characters straight out of the box. I found that using the DejaVuSansMono.ttf font allows you to render the characters properly.

Related

How to include images in xhtml2pdf generated pdf files?

I am running a streamlit app which generates reports containing images and dataframes. I have used jinja2 to generate the html file from a template. Then, I would now like to convert to a pdf file using xhtml2pdf to download.
How to do that?
from jinja2 import Environment, FileSystemLoader
def convert_html_to_pdf(source_html, output_filename="temp/report.pdf"):
result_file = io.BytesIO()
pdf = pisa.CreatePDF(
source_html,
dest=result_file)
return pdf.getvalue()
def load_template():
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('catAnalysisTemplate.html')
return template
def render_report(data, filename="report"):
template = load_template()
html = template.render(data)
# with open(f'temp/{filename}.html', 'w') as f:
# f.write(html)
pdf = convert_html_to_pdf(html)
return [html, pdf]
This works fine except the images are not included in the pdf file. My static images are stored in
img/
logo.png
and the charts I may generate it in memory as like
def plot_co_attainment(qp):
img = io.BytesIO()
data = qp.co_attainment()[["Level", "Perc_Attainment"]]
plt.figure(dpi=150)
plt.bar(data["Level"], data["Perc_Attainment"], width=0.5, color=colors)
for i, val in enumerate(data["Perc_Attainment"].values):
plt.text(i, val, str(val) + "%",
horizontalalignment='center',
verticalalignment='bottom',
fontdict={'fontweight': 500, 'size': 20})
plt.xlabel("Course Outcomes")
plt.ylabel("Percentage of Attainment")
plt.ylim((0, 110))
plt.savefig(buf, format='jpg')
return buf
How do I connect the dots and get the images in my pdf file?
I am having the same issue. The way I solved it was to use a link_handler and return the data as a data: uri containing the png image data.
This example will take the src attribute and use it to generate a square image in that color, which will be embedded in the PDF. Sadly this doesn't let you modify the image tag itself so you can't change the sizes/classes or anything else.
Using something like this opens the way to embedding just about anything without having to add them to your template directly.
from base64 import b64encode
from io import BytesIO
from xhtml2pdf import pisa
from PIL import Image
html_src = """
<body>
<div>
<img src="red"/>
<img src="green"/>
<img src="blue"/>
</div>
</body>
"""
def link_callback(src_attr, *args):
"""
Returns the image data for use by the pdf renderer
"""
img_out = BytesIO()
img = Image.new("RGB", (100, 100), src_attr)
img.save(img_out, "png")
return f"data:image/png;base64,{b64encode(img_out.getvalue())}"
def main():
with open("one.pdf", "wb") as f:
pizza = pisa.CreatePDF(
html_src,
dest=f,
link_callback=link_callback,
)
if __name__ == "__main__":
main()

How to convert an uploaded file (InMemoryUploadedFile) from pdf to jpeg in Django using wand?

I'm trying to convert a pdf file uploaded in Django to a jpg file. I would like to use the file directly in the InMemoryUploadedFile state.
I tried to use wand but without any success.
Here is the code I wrote:
from django.shortcuts import render
from wand.image import Image as wi
# Create your views here.
def readPDF(request):
context = {}
if request.method == 'POST':
uploaded_file = request.FILES['document']
if uploaded_file.content_type == 'application/pdf':
pdf = wi(filename=uploaded_file.name, resolution=300)
pdfImage = pdf.convert("jpeg")
return render(request, 'readPDF.html', {"pdf": pdfImage})
I tried different things like using uploaded_file.file or uploaded_file.name as the first argument for the wand image but without any success.`
I thank you in advance for your help!
Should be able to pass InMemoryUploadedFile directly to Wand's constructor.
uploaded_file = request.FILES['document']
if uploaded_file.content_type == 'application/pdf':
with wi(file=uploaded_file, resolution=300) as pdf:
# ...
However, I wouldn't recommend attempting to convert PDF pages to JPEGs in a HTTP request. Best to write the document to storage, and have a background worker manage the slow / unsafe tasks.

Append .png image to a pdf using reportlab in Django framework

I'm using Django and reportlab to generate a PDF report
I already can generate the pdf, but I Wanted to append a logo.png to it.
these were the lines I added in
views.py:
from reportlab.platypus import Image
logo = Image("/cdss/static/cdss/img/logo.png")
exam.append(logo)
But it isn't working, Am I exporting the Image() method wrong? Or is Path to the file wrong?
Hope you can help me, thanks ;)
This Worked For me....
def PrintImage(request,std_id):
response = HttpResponse(content_type='application/pdf')
doc = SimpleDocTemplate(response,topMargin=2)
doc.pagesize = landscape(A6)
elements = []
I = Image('http://demoschoolzen.educationzen.com/images/tia.png')
I.drawHeight = 0.7*inch
I.drawWidth = 0.7*inch
elements.append(I)
doc.build(elements)
return response
and Call it from your URLs

How to use Xhtml2PDF convertor in linux system?

I am trying to convert html to pdf in django using xhtml2pdf, and successfully converted html to pdf in windows but in linux it is giving me file permission error though i give all type of permission to that file.Here i am posting taht function that convert html to pdf please suggest any solution thanks in advance.
def CreatePDF(request):
ser_type=request.POST.get("service_type")
if ser_type is not None:
data=WalletTransaction.objects.get(order_id=request.POST.get("order_id"),user=request.user)
c={'data':data,'ser_type':int(ser_type)}
template = get_template('TransHistoryPdf.html')
html = template.render(c)
file = open('test.pdf', "w+b")
pisaStatus = pisa.CreatePDF(html.encode('utf-8'), dest=file,
encoding='utf-8')
file.seek(0)
pdf = file.read()
file.close()
return HttpResponse(pdf, 'application/pdf')

How to include Google Chart inside Pisa Document xhtml2pdf with Django

I'm trying to embed the Google Chart url below into a Pisa xhtml2pdf PDF, but can't seem to make it work.
http://chart.apis.google.com/chart?cht=bvs&chd=t:425.9,550.6&chs=400x125&chds=0,600&chl=Aug%2009%7CSep%2009&chco=8BC542&chbh=32,24
I was hoping this post would solve my problem but no luck.
I'm using the following code (taken from the aforementioned post)
html = render_to_string('reporting/pdf.html', keys,
context_instance=RequestContext(request))
result = StringIO.StringIO()
pdf = pisa.pisaDocument(
StringIO.StringIO(html.encode('ascii', 'xmlcharrefreplace')),
result, link_callback=link_callback)
return HttpResponse(result.getvalue(), mimetype='application/pdf')
and
def link_callback(uri, rel):
if uri.find('chart.apis.google.com') != -1:
return uri
if uri.find('mydomain.com') != -1:
return uri
return os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
It works when I embed images from mydomain.com but I get nothing when trying to link to chart.apis.google.com
This works:
<img src="http://mydomain.com/foo.jpg>
This is broken:
<img src="http://chart.apis.google.com/chart?cht=bvs&chd=t:425.9,550.6&chs=400x125&chds=0,600&chl=Aug%2009|">
Any help would be greatly appreciated. Cheers.