django export images and text in the html as pdf - django

I was having trouble exporting images in an html file as pdf, a similar solution exists here.
The html is being rendered properly on the server. I verified it by cross checking it on a url.
but while trying to download/render the pdf **i get a pdf but which is blank, also it says error in the third line of the download function in views.py
Here is what i tried:
html file:
<html>
<head>
<link href="{{ STATIC_URL }}css/certificate.css" rel="stylesheet"
type="text/css" />
</head>
<body>
<div class="certificate_container">
<div class="statictext">
<p>{{ name }}</p>
</div>
</div>
</body>
<html>
css file:
body{margin:0px; padding:0px;}
.certificate_container{ width:792px; height:612px; background:url("../images/certificate.gif") no-repeat;}
.statictext{width:400px; margin:0px auto; padding-top:240px; height:30px; text-align:center; font:bold 14px Arial, Helvetica, sans-serif; color:#333;}
views.py:
#relevant imports
from reportlab.pdfgen import canvas
import xhtml2pdf.pisa as pisa
import cStringIO as StringIO
def download(request):
html = render_to_string("certificate.html", { 'pagesize' : 'A4', }, context_instance=RequestContext(request))
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(), dest=result, link_callback=fetch_resources )
if not pdf.err:
return HttpResponse(result.getvalue(), mimetype='application/pdf')
return HttpResponse('Gremlins ate your pdf! %s' % cgi.escape(html))
def fetch_resources(uri, rel):
path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
return path
def home(request):
return render(request, 'certificate.html', {'name':'user1'} )
The urls have been taken care of properly.

I later found, this could not be achieved using the above tech stack, hence i tried getting a template image and used PIL to modify it based on context. And that worked.

Related

unable to use the variable in django

i recently started my django course online nad getting some problem.
i am not able to use my variable which i passed from index.html to about.html.
but in about.html it is not shown up.
.py file code :
from django .http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request , 'index.html')
def about(request):
t1 = print(request.GET.get('text' , 'default'))
return render(request , 'about.html' , t1)
index.html file code:
<!DOCTYPE html>
<html>
<head>
<title>template</title>
</head>
<body>
<h1> hello everyone </h1>
<form action="/about" , method="get">
<textarea name="text" style="margin: 0px; width: 1245px; height: 171px;"></textarea>
<input type="submit" name="OK">
</form>
</body>
</html>
about.html file code :
<!DOCTYPE html>
<html>
<head>
<title>template</title>
</head>
<body>
<h1>you typed {{t1}}</h1>
</form>
</body>
</html>
print(..) does not return anything. You can pass the variable to the context, for example:
def about(request):
return render(
request ,
'about.html' ,
{'t1': request.GET.get('text' , 'default')}
)

How to piece together a simple flask web app

I'm trying to build a small web app. A simple price scraper. I'm trying to piece it together into a web app without success.
Here's my working piece of python code I have, that returns the price of the specific item which is :
918193-012
Basically the idea is : a user would input a stock code of a product, and in return, on the same page/or the other page, he would receive the price for that product. Any advices are appreciated.
import requests
from bs4 import BeautifulSoup
import subprocess
url = f'https://www.tennis.fr/catalogsearch/result/?q=918193-012'
response = requests.get(url)
soup = BeautifulSoup(response.text, "html.parser")
capturedPrice = soup.findAll('p', class_="special-price")[0].text
capturedPrice = capturedPrice.strip('0')
capturedPrice = capturedPrice.strip()
print(capturedPrice[35:])
Here's my app.py
from flask import Flask, jsonify, render_template, request
from bs4 import BeautifulSoup
import subprocess
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
An here's: the index.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono&display=swap" >
<style>
body {
font-family: 'Roboto Mono', monospace;
}
* {
box-sizing: border-box;
}
form.example input[type=text] {
padding: 10px;
font-size: 17px;
border: 1px solid grey;
float: left;
width: 80%;
background: #f1f1f1;
}
form.example button {
float: left;
width: 20%;
padding: 10px;
background: #2196F3;
color: white;
font-size: 17px;
border: 1px solid grey;
border-left: none;
cursor: pointer;
}
form.example button:hover {
background: #0b7dda;
}
form.example::after {
content: "";
clear: both;
display: table;
}
</style>
</head>
<body>
<center>
<h1>Find the best prices</h1>
<p><h4>Stock code to test: 918193-012</h3></p>
<form class="example" action="" style="margin:auto;max-width:500px">
<input type="text" placeholder="Stock code" name="">
<button type="submit"><i class="fa fa-search"></i></button>
</form>
</center>
</body>
</html>
You want to extract Input-Information from your HTML Site. A possible solution would be to use a form:
app.py:
from flask import Flask
from flask_wtf import FlaskForm
from flask import render_template
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
app = Flask(__name__)
class InputForm(FlaskForm):
input = StringField('Input',validators=[DataRequired()]
submit = SubmitField('Search for Price')
#app.route('/')
def index():
form = InputForm()
if form.validate_on_submit():
result = form.input.data
return render_template("index.html", result=result, form=form)
else:
return render_template("index.html",form=form)
if __name__=="__main__":
app.run(debug=True)
You can change the StringField to IntegerField if you want to, thats on you.
Next step would be to add sth to your #app.route:
Ofcourse you need to add some code to your HTML Site to pass the Search-Value to the Web App.
instead of your normal html button you need to pass the form:
<!DOCTYPE html>
<html>
<head>
##your css stuff##
<style>
</style>
</head>
<body>
<center>
<h1>Find the best prices</h1>
<p><h4>Stock code to test: 918193-012</h3></p>
{{ form.input(class="form-control") }}
{{ form.submit(class="btn") }}
{% if result == #yourvalue# %}
#your printed data#
{% else %}
{% endif %}
</center>
</body>
</html>
in this example bootstrap is used for design but thats changable the way you want it
I hope my text was understandable
Edit 1:
You use an if statement inside the html site if you want to use just one html file. With my example you pass the result to the html with the render_template line.

Exporting html with arabic characters to pdf using django

I am trying to export my html page into pdf using Pisa library in django, But I have problems with arabic characters when I get the pdf output
i visit this site https://www.codingforentrepreneurs.com/blog/html-template-to-pdf-in-django/
here my code
from .utils import render_to_pdf #created in step 4
class GeneratePdf(View):
def get(self, request, *args, **kwargs):
tar= u"محاولة"
data = {'dem1': dem1,'dem2':dem2,'tar':tar}
pdf = render_to_pdf('pdf2.html', data)
return HttpResponse(pdf, content_type='application/pdf')
here the template
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html"; charset=UTF-8">
<style type='text/css'>
#font-face {
font-family: "DejaVuSansMono";
src: url("/static/fonts/DejaVuSansMono.ttf");
}
body { font-family: DejaVuSansMono; }
</style>
</head>
<body>
<p>محاولة الكتابة باللغة العربية</p>
<p>here the variable = {{tar}}</p>
</body>
</html>
i have symbols in place of arabic characters

How to properly configure route to show only subdirectories?

I am unable to download a csv from sub-directory but I can do it from a home directory.
I've tried changing routes to the subdirectory, but it throws 404 error.
#app.route('/', defaults={'req_path': 'Categorized%20Output/2019-06-27'})
#app.route('/<path:req_path>')
def index(req_path):
# data = dataset.html
#return dataset.html
folderLocation = os.path.dirname(__file__)
print(folderLocation)
abs_path = os.path.join(folderLocation,req_path)
print(abs_path)
# Return 404 if path doesn't exist
if not os.path.exists(abs_path):
return abort(404)
# Check if path is a file and serve
if os.path.isfile(abs_path):
return send_file(abs_path)
# Show directory contents
files = os.listdir(abs_path)
return render_template('index.html',files = files)
if __name__ == "__main__":
app.run()
My CSV's are located in multiple subfolder named as different dates in FolderLocation/Categorized Output/lot's of dates folder/
The index.html file from templates
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}"/>
<title>Show CSV</title>
</head>
<body>
<div class="table">
<ul>
{% for file in files %}
<li>{{ file }}</li>
{% endfor %}
</ul>
</div>
</body>
I want to be able to download CSV's from all different dates subfolder.
An example of the location of CSV's is: "127.0.0.1:5000/Categorized%20Output/2019-06-27"
I found a convenient way to grab a file/directory recently by using easygui.
pip install easygui
import easygui
#app.route('/')
def index():
get_a_file = easygui.fileopenbox()
files = get_a_file # do some stuff with your file
return render_template('index.html', files=files)
This answer doesn't address the root of your issue, but if it helps and you're interested you can read the easygui documentation.
if you want to start with a specific directory you can customize fileopenbox such as..
files = easygui.fileopenbox(
msg='some message',
title='some title',
default='c:\some_directory\some_directory\*.file_type',
filetype='*.file_type'
)
where file_type is any type of file.. .txt, .dat, etc.,

How to incorporate Reportlab with Django Class Based View?

I am trying to convert my HTML to a PDF. I watched this tutorial, https://www.codingforentrepreneurs.com/blog/html-template-to-pdf-in-django/ and I was able to successfully get the tutorial to work with hardcoded values. The problem is...I can't figure out how to dynamically incorporate my model and it's attributes into this example.
Here are the steps I followed...
First I installed reportlab into my environment with the following version...
pip install --pre xhtml2pdf
This worked...
Then I added a utils.py file to my project as instructed.
Then I copied this code into my utils.py file...
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
Then I created an HTML file like the one below:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Title</title>
<style type="text/css">
body {
font-weight: 200;
font-size: 14px;
}
.header {
font-size: 20px;
font-weight: 100;
text-align: center;
color: #007cae;
}
.title {
font-size: 22px;
font-weight: 100;
/* text-align: right;*/
padding: 10px 20px 0px 20px;
}
.title span {
color: #007cae;
}
.details {
padding: 10px 20px 0px 20px;
text-align: left !important;
/*margin-left: 40%;*/
}
.hrItem {
border: none;
height: 1px;
/* Set the hr color */
color: #333; /* old IE */
background-color: #fff; /* Modern Browsers */
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='header'>
<p class='title'>Invoice # </p>
</div>
<div>
<div class='details'>
Bill to: {{ customer_name }} <br/>
Amount: {{ amount }} <br/>
Date:
<hr class='hrItem' />
</div>
</div>
</body>
</html>
I also created the necessary URL....
Then I created a view similar to what is defined below:
from django.http import HttpResponse
from django.views.generic import View
from yourproject.utils import render_to_pdf #created in step 4
class GeneratePdf(View):
def get(self, request, *args, **kwargs):
data = {
'today': datetime.date.today(),
'amount': 39.99,
'customer_name': 'Cooper Mann',
'order_id': 1233434,
}
pdf = render_to_pdf('pdf/invoice.html', data)
return HttpResponse(pdf, content_type='application/pdf')
When I click on my link to this view...the output shows just like the tutorial says...
However, if I am trying to get my model to display in this format...I'm stumped as to how to do that. I tried a DetailView....and then I get the data but no PDF....I've also searched many other places and I can't seem to find an example that would allow me to get my model dynamically and pull in attributes as needed...Thanks in advance for any help or pointers.
If you want to use DetailView, I think you can do it like this:
class SomeDetailView(DetailView):
model = YourModel
template_name = 'pdf/invoice.html'
def get_context_data(self, **kwargs):
context = super(SomeDetailView, self).get_context_data(**kwargs)
# add extra context if needed
return context
def render_to_response(self, context, **kwargs):
pdf = render_to_pdf(self.template_name, context)
return HttpResponse(pdf, content_type='application/pdf')
Here I am overriding render_to_response to override the default response from DetailView to return a PDF response. Here, the context that comes in are from get_context_data. in get_context_data you can add any extra context if needed.