I want to generate a PDF using the following approach found on the Django 1.9 docs: https://docs.djangoproject.com/ja/1.9/howto/outputting-pdf.
Here is my url pattern (I don't need anything special, just a different url name like so
urlpatterns = [
url(r'^people/$', PeopleTemplate.as_view(), name='people'),
url(r'^people/pdf/$', some_view),
]
def some_view(request):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="example.pdf"'
p = canvas.Canvas(response)
p.drawString(100, 100, "Hello world.")
p.showPage()
p.save()
def get(self, request, *args, **kwargs):
context = locals()
context['response'] = self.response
context['p'] = self.p
return render_to_response(self.response_template, context, context_instance=RequestContext(request))
I'm trying to use a get method. This prompts for a pdf output when I hit /pdf, but doesn't contain any data - just a blank page. How do I get data that exists at this url /attendance/ to show on the pdf page when you hit the /attendance/pdf url?
I think you need to:
render html
convert it to pdf
set pdf content to response body
return response
Now your code renders template as html, adds 'application/pdf' content type to headers and returns normal html page.
You need something like PDFTemplateView. There are ready to use packages django-easy-pdf or django-wkhtmltopdf.
UPD:
def some_view(request):
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="example.pdf"'
p = canvas.Canvas(response)
// simple but visual result is not pretty at all
for i, obj in enumerate(People.objects.all()):
p.drawString(100, 50*(i+1), str(obj))
p.showPage()
p.save()
def get(self, request, *args, **kwargs):
context = locals()
context['response'] = self.response
context['p'] = self.p
return render_to_response(self.response_template, context, context_instance=RequestContext(request))
Related
I am trying to get my view to redirect to another page after clicking a button that triggers the POST request. I cannot seem to figure out why the redirect doesn't work or why it doesn't even seem to try to redirect.
Here is my view:
def cart1(request):
if request.user.is_authenticated:
#POST
if request.method == "POST":
#JSON Data
data = request.body
new_data = ast.literal_eval(data.decode('utf-8'))
customer = request.user
user_order = Order(user=customer)
user_order.save()
x = 0
while x < len(new_data.keys()):
obj_title = new_data[x]["title"]
obj_price = new_data[x]["price"]
obj_quantity = new_data[x]["quantity"]
obj_extra = new_data[x]["extra"]
total = round(float(obj_price.replace("$", "")))
m = OrderItem(order=user_order, title=obj_title, price=total, quantity=obj_quantity, extra=obj_extra)
m.save()
x += 1
return redirect('checkout-page')
return render(request, 'cart.html')
Any help would be appreciated, thank you
redirect(…) [Django-doc] produces a HttpRedirectResponse, you need to return it, so:
return redirect('checkout-page')
redirect(…) itself thus does not stop the code flow to redirect return a HTTP redirect response, it constructs such response, and your view should then return that response.
you need to be sure the URL name =checkout-page is in the current app otherwise you need to make it redirect('app:checkout-page')
However,I suggest to use from django.http import HttpResponseRedirect
#adm.route('/list_users', methods=['GET'])
#login_required`enter code here`
#admin_permission.require(http_exception=403)
def list_users():
try:
if (request.content_type.startswith('application/json')):
def processjsonlist():
#csrf.exempt
try:
page = request.args.get('page', 1, type=int)
recs = current_app.config.get('RECORDS_PER_PAGE')
list_user = Person.query.order_by(
Person.id).paginate(page, recs, False)
rv = []
for person in list_user.items:
tmp = {}
tmp['id']=person.id
tmp['username'] = person.username
tmp['first_name'] = person.first_name
tmp['middle_name'] = person.middle_name
tmp['last_name'] = person.last_name
tmp['employee_code'] = person.employee_code
tmp['active'] = person.active
tmp['email'] = person.email
tmp['mobile'] = person.mobile
tmp['roles'] = [role.description for role in person.roles]
rv.append(tmp)
return jsonify({"data": rv})
except Exception as error:
return jsonify(error=repr(error))
else:
page = request.args.get('page', 1, type=int)
recs = current_app.config.get('RECORDS_PER_PAGE')
pagination = Person.query.order_by(
Person.id).paginate(page, recs, False)
search_form = SearchForm()
return render_template('adm/user_list.html', pagination=pagination,
search_form=search_form)
except Exception as e:
flash_exception(e, 'danger')
return redirect(url_for('adm.getIndex'))
You cannot render both HTML and JSON in the same response for a single request. However, you can allow the Accept header to determine whether an endpoint renders HTML or JSON. The entire response must be one or the other, but can't be mixed. I haven't used flask, so I don't know the exact details of how to do this with your project. Hopefully this will give you some terms to help with your google search.
I am trying to print invoice in PDF format in Django I used xhtml2pdf to convert HTML doc. to PDF but when I try to run my code it gives me this error :
LayoutError at /invoice/ Flowable <PmlTable#0x1D09C899130 7 rows x 5 cols(tallest row 841)> with cell(0,0) containing '<PmlKeepInFrame at 0x1d09b77d670> size=x'(538.5826771653543 x 5893.228346456693), tallest cell 841.9 points, too large on page 2 in frame 'body'(538.5826771653543 x 785.19685039370
this is in my views.py
from django.http import HttpResponse
from django.views.generic import View
from booking.utils import render_to_pdf
from django.template.loader import get_template
class GeneratePDF(View):
def get(self, request, *args, **kwargs):
template = get_template('invoice.html')
context = {
"invoice_id": 1234,
"customer_name": "John Cooper",
"amount": 1399.99,
"today": "Today",
}
html = template.render(context)
pdf = render_to_pdf('invoice.html', context)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Invoice_%s.pdf" %("12341231")
content = "inline; filename='%s'" %(filename)
download = request.GET.get("download")
if download:
content = "attachment; filename='%s'" %(filename)
response['Content-Disposition'] = content
return response
return HttpResponse("Not found")
and this is my urls.py
from django.urls import path
from booking.views import GeneratePDF
app_name = 'booking'
urlpatterns = [
path('invoice/', GeneratePDF.as_view(), name ="invoice"),
]
I got the answer
xhtml2pdf is not able to split table cells that are larger than the available space. To work around it you may define what should happen in this case. The -pdf-keep-in-frame-mode can be one of: “error”, “overflow”, “shrink”, “truncate” where “shrink” is the default value.
table { -pdf-keep-in-frame-mode: shrink;}
documentation link
I am trying to send a pdf as a Gmail attachment in Django, which is just generated by the same view. For generating the pdf, I use to try this tutorial link.
my views.py:
def submit_report(request, pk):
template = get_template('app/pdf_rprt.html')
Industry_obj = Industry.objects.get(id=pk)
Industry_Report_obj = Industry_obj.industry_report_set.all()
report_tableA_obj = report_tableA.objects.filter(industry_report__industry=Industry_obj)
context = {
'industry' : Industry_obj,
'Industry_Report' : Industry_Report_obj,
'report_tableA' : report_tableA_obj,
}
html = template.render(context)
pdf = render_to_pdf('app/pdf_rprt.html', context)
if pdf:
to = "kanchon2199#gmail.com"
email = EmailMultiAlternatives(
#subject =
"final report sending (beta)",
#content =
'hello, this is test report sending mail',
#from email
settings.EMAIL_HOST_USER,
#list of recipent
[to]
)
email.attach_file(pdf)
email.send()
return redirect('app:index')
here the render_to_pdf comes from a custom build function in utils.py:
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
But it says error like (for the line email.attach_file(pdf)):
TypeError at /submit_report/1/
expected str, bytes or os.PathLike object, not HttpResponse
How can I fix it?
However, I have found a solution to this problem. the return type of render_to_pdf inside the utils.py should be ContentFile like this:
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 ContentFile(result.getvalue(), 'sampleReport.pdf')
return None
and inside views.py the email.attach_file() need dir path inside it, so we can use our database to save the pdf file and then attach it like this:
def submit_report(request, pk):
template = get_template('app/pdf_rprt.html')
context = {
'industry' : Industry_obj,
'Industry_Report' : Industry_Report_obj,
'report_tableA' : report_tableA_obj,
}
html = template.render(context)
pdf = render_to_pdf('app/pdf_rprt.html', context)
if pdf:
Final_report_obj = Final_report.objects.create(pdf=this_pdf)
Final_report_obj.save()
to = [gmail1#gmail.com, gmail2#gmail.com.....]
email = EmailMultiAlternatives(
"your Subject",
"your content.... ",
settings.EMAIL_HOST_USER,
to
)
email.attach_file(os.path.join(settings.MEDIA_ROOT, Final_report_obj.pdf.name))
email.send()
return redirect('app:index')
Here I use the Final_report_obj named model just to store my pdf file, we can use another type of model also.
I am trying to fill a livecycle created form with form data from django. Now I think I have the code done correctly but I am having a hard time with the structure of the livecycle form. Currently I have the ability to populate pdf's created with adobe acrobat but not livecycle. Is there a certain file structure for livecycle?
Here is the function I call to fill the pdf:
def print_rdba(client=None, data=None, investment_form=None):
from django.http import HttpResponse
from clients.models import Client
from dateutil.parser import parse
from settings import URL
from datetime import date
file = ''
print data
fdf = '<?xml version="1.0" encoding="UTF-8"?>\n<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">\n\t<fields>'
fdf += fdf_val_str("primary1_lastname", data.get('lastname'))
fdf += fdf_val_str("primary1_firstname", data.get('firstname'))
if investment_form:
file = "%s%s" % (URL, investment_form.file.url)
fdf += '''</fields>
<f href="%s" target="_blank"/>
</xfdf>''' % file
fdf = fdf.replace('^M', '')
response = HttpResponse(fdf.encode("ISO-8859-1"), mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=form.xfdf'
return response
Here is fdf_val_str:
def fdf_val_str(field, val):
val = str(val).replace('&','&')
return '<field name="%s"><value>%s</value></field>\n' % (field, val)
My clients edit function in my views.py:
#login_required
#user_passes_test(lambda u: u.is_staff or u.rep_set.get().add_clients, login_url='/')
def edit(request, client=None, *args, **kwargs):
from clients.forms import ClientForm
from entity.forms import LocationForm
from investments.models import InvestmentForm
from lib.tools import print_rdba
...
rdba_btn = InvestmentForm.objects.get(id=3)
context = {}
...
if request.POST.has_key('submit-%s' % rdba_btn.code):
request.user.message_set.create(message='Generating PDF form')
return print_rdba(client=client, data=form.data, investment_form=rdba_btn)
Any help would be much appreciated
Do you have LiveCycle Forms installed? You could then generate the XML data with DJango and sending it to LiveCycle to render the PDF Form
edit:
And you should notice LiveCycle Designer generates XFA-based forms, which differ from XFDF