I'm trying to fill pre-made pdf form with database data and flatten it. For example, if the user inputs a field called "name", it should be placed in the name field of the pdf form.
You can use reportlab library in combination with Django views :
from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
buffer = BytesIO()
# Create the PDF object, using the BytesIO object as its "file."
p = canvas.Canvas(buffer)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
Django documentation : https://docs.djangoproject.com/en/1.9/howto/outputting-pdf/
Reportlab documentation : http://www.reportlab.com/documentation/
Related
I use python 3.6 Django, my code looks like this:
from docx import Document
document = Document()
document.add_heading('My docx', 0)
document.save('myFile.docx')
return HttpResponse(document, content_type='application/vnd')
I don't want to save it on server, instead I want to send it to client side using ajax and save it on client pc.
Any thoughts how to do it?
I was never in touch with ajax but I know how to present your file as a download without saving it in more as a temporary buffer.
You did not present the full function or method of your code. Therefore I am giving a get() method of a class-based view as an example.
Try this:
import io
from django.http import FileResponse
def get(self):
document = Document()
document.add_heading('My docx', 0)
buffer = io.BytesIO() # create buffer
doc.save(buffer) # save doc to buffer
buffer.seek(0) # returns the curser to the beginning of the bytestream
return FileResponse(buffer, as_attachment=True, filename=f"your_file.docx")
Read more about FileResponse here.
I can create a PDF file using reportlab in a Django application. However, I can't add it into a FileField in a model. I wonder how to transfer an io.BytesIO data into FileField in Django.
This is summary of my views.py.
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics
buffer = io.BytesIO()
cc = canvas.Canvas(buffer, pagesize=A4)
# describe something
font_name = "HeiseiKakuGo-W5"
cc.registerFont(UnicodeCIDFont(font_name))
cc.setFont(font_name, 7)
cc.drawString(65*mm, 11*mm, 'test')
cc.showPage()
cc.save()
buffer.seek(0)
exampleObject= get_object_or_404(SomeModel, pk=self.kwargs['pk'])
exampleObject.exampleFileField.save('test.pdf', File(buffer)) # here! this sentence doesn't work.
exampleObject.save()
return FileResponse(buffer, as_attachment=True, filename='test.pdf')
The point is the sentence below doesn't work. I think "File(buffer)" is not appropliate.
exampleObject.exampleFileField.save('test.pdf', File(buffer))
Although once I tried to save a pdf into a FileField after creating a pdf file in a directory as a temporaly file, I prefer to do it by using io.BytesIO.
I believe your missing buffer.get_value()
I also use ContentFile instead of File though not sure it's necessary.
I just tested the following snippet and it works using reportlab==3.5.32
import io
from django.core.files.base import ContentFile
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from my_app.models import MyModel
buffer = io.BytesIO()
canv = canvas.Canvas(buffer, pagesize=A4)
canv.drawString(100, 400, "test")
canv.save()
pdf = buffer.getvalue()
buffer.close()
my_object = MyModel.objects.latest("id")
my_object.file_field.save("test.pdf", ContentFile(pdf))
You may need to seek(0) on your buffer, since it's been used previously, I wouldn't be surprised the buffer would be at the end and result in an empty file saved in Django.
I use Django 2.1.4 and use Django sample for create pdf report
def some_view(request):
# Create a file-like buffer to receive PDF data.
buffer = io.BytesIO()
# Create the PDF object, using the buffer as its "file."
p = canvas.Canvas(buffer)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
# FileResponse sets the Content-Disposition header so that browsers
# present the option to save the file.
return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
It started dowloaded but never finished. What is wrong?
Old version works properly
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
I would look at this example (except for the queryset),, see if that works, similar worked for me earlier today, How can i display my data in database and export it to pdf -Django
Get the value of the BytesIO buffer and write it to the response.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="WishList.pdf"'
from reportlab.pdfgen import canvas
buffer = BytesIO()
p = canvas.Canvas(buffer)
p.drawString(100, 100, "Hello world.")
p.showPage()
p.save()
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
Believe it or not, the old version is the way I recommend that you do it. To get this working with a FileResponse, try the below:
# FileResponse sets the Content-Disposition header so that browsers
# present the option to save the file.
response = FileResponse(buffer, as_attachment=True, filename='hello.pdf', content_type='application/pdf')
# set the content length to let the browser know how many bytes to expect
response['Content-Length'] = bugger.getbuffer().nbytes
return response
my x variable is getting all the data in my database, i guess? someone help me how can i display all data and export it to pdf file.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="WishList.pdf"'
buffer = BytesIO()
# Create the PDF object, using the BytesIO object as its "file."
p = canvas.Canvas(buffer)
x = Item.objects.all()
p.drawString(100, 100,x)
p.drawString(200,300,"sad")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
Your variable x won't return anything you can print into the PDF, because its a queryset and not a couple strings attached to each other. I just started working with Django and getting the values works something like this:
x = Item.objects.all[0].name
This code snippet will assign the vale of the row name of the first entry in your Item table to the variable x.
For more Information I can only recommend reading the Tutorial about writing queries on the django website.
I found this handy code in the Django Docs:
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
I would like to pass a variable to the function as variable name, but cannot figure it out (though I am sure it is super easy).
Anyone have an idea?
Thanks so much!
filename="somefilename.pdf" there is place where you can determine your filename.
You can use it as:
filename = 'somefilename.pdf'
response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
Hope it might helps you:
Add one more argument named "name" to the view "some_view" and replace the filename with the argument value.
def hello_pdf(request, name):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=%s.pdf'% name
temp = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response
Check the name argument replacing the filename in the 4th line of code. Also don't forget to update the urls.py like below:
url(r'^(?P<name>\w+)/$', 'app.some_view')
After all pass the filename you wish to replace with url like below:
http://yourwebsite.com/name-of-file/
If you want to force viewing the PDF in browser with given filename but without automatic download, you can use "inline" instead of "attachment":
response["Content-Disposition"] = f'inline; filename="{file_name}"'