I am in a django project and trying to generate multiple PDF files in a loop condition using reportlab.
view.py
def pdftest(request, *args, **kwargs):
if request.method == 'POST':
for x in range(0, 3):
response = HttpResponse(content_type='application/pdf')
buffer = BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=portrait(letter))
elements = []
ptext = 'Hellow World! --- %s' %x
styles=getSampleStyleSheet()
elements.append(Paragraph(ptext, styles['Normal']))
doc.build(elements)
response['Content-Disposition'] = 'attachment; filename="{}"'.format('test.pdf')
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
context = {}
context['title'] = 'PDF TEST'
return render(request, 'companies/pdftest.html', context)
But my program produce only one PDF. Do you have any idea about this problem?
You’re calling return response in the first pass of your loop so obviously your program never reaches the second or third pass.
Related
I generate pdf files about each models object, but in pdf, I can't write with Georgian letters, it returns black squares.
Here is some code, I am using from xhtml2pdf import pisa
in my urls.py :path('pdf/', views.customer_render_pdf_view, name='customer-pdf-view')
def customer_render_pdf_view(request, *args, **kwargs):
pk = kwargs.get('pk')
customer = get_object_or_404(id, pk=pk)
template_path = 'test.html'
context = {'customer': customer}
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename= "report.pdf"'
template = get_template(template_path)
html = template.render(context)
pisa_status = pisa.CreatePDF(
html,
dest=response,
encoding='utf-8'
)
# if error then show some funny view
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return response
You are just using a font that doesn't contain your letters. You need to use a font that does have them.
https://xhtml2pdf.readthedocs.io/en/latest/reference.html?highlight=Font#using-custom-fonts
I have created an API that allows me to upload an image using the POST method in POSTMAN. After submission, I want to display that image name after making a GET request. I am not using any model and I don't intend to grab the image from the directory it is stored in; since I will be uploading images in a server later.
I have looked at multiple sources. A few examples are this, and this.
This is my current code so far but not successful:
views.py:
class API(APIView):
parser_classes = (MultiPartParser,)
def get(self, request, *args, **kwargs):
name = self.request.GET.get('image')
if name:
return Response({"img_name": name}, status=200)
return Response({"img_name" : None}, status = 400)
def post(self, request):
file = self.request.data
img_file = file['image'] #store the image data in this variable
if img_file:
uploaded_file = img_file
img = [{"image_name": uploaded_file}]
serializer = ImgSerializer(img, many = True).data
return Response(serializer, status = 200)
else:
return Response("Please upload", status = 400)
serializers.py:
from rest_framework import serializers
class ImgSerializer(serializers.Serializer):
image_name = serializers.CharField()
My expected result within GET request should be like this:
{'image_name' : 'image_name_from_POST_Request'}
But I am getting this result instead:
None
How can I pass data from the POST request to the GET request using Django's rest framework? Is there an efficient way to deploy this requirement without using a model?
I figured it out. I just created a JSON file in the POST method and stored the necessary data in it. Finally, in order to view the data within the GET method, I opened the file and returned it as a Response.
views.py:
class API(APIView):
parser_classes = (MultiPartParser,)
def get(self, request):
with open('data.txt') as json_file:
data = json.load(json_file)
if data:
return Response(data, status=200)
return Response({"name" : None}, status = 400)
def post(self, request):
posted_file = self.request.data
img_file = posted_file['image']
if img_file:
uploaded_file = img_file
data = [{"image_name": uploaded_file}]
json_data = {"image_name": uploaded_file}
data = {}
data['key'] = []
data['key'].append(json_data)
with open('data.txt', 'w') as outfile:
json.dump(image, outfile)
serializer = ImgSerializer(image, many = True).data
return Response(serializer, status = 200)
else:
return Response(serializer.errors, status = 400)
So I am trying to serve a static file through a simple Django Rest framework function view. It gives me 200 code but doesn't download the file.
Here is the code :
#api_view(['POST'])
def download_file(request):
if request.method == 'POST':
serializer = MySerializer(data=request.data)
filename = 'file.xlsx'
file_full_path = "src/{0}".format(filename)
with open(file_full_path, 'rb') as f:
file = f.read()
response = HttpResponse(file, content_type="application/xls")
response['Content-Disposition'] = "attachment; filename={0}".format(filename)
response['Content-Length'] = os.path.getsize(file_full_path)
return response
return Response(status=status.HTTP_400_BAD_REQUEST)
What am I doing wrong here?
You are trying to download file with a HTTP POST method, I don't think it's a nice way. So try HTTP GET for downloading. If you wish to provide extra arguments (payload in POST method), you could do it using Query Parameter as /api/end/point/?param=value1¶m2=value2.
So, try the following snippet,
#api_view(['GET'])
def download_file(request):
if request.method == 'GET':
filename = 'file.xlsx'
file_full_path = "src/{0}".format(filename)
with open(file_full_path, 'rb') as f:
file = f.read()
response = HttpResponse(file, content_type="application/xls")
response['Content-Disposition'] = "attachment; filename={0}".format(filename)
response['Content-Length'] = os.path.getsize(file_full_path)
return response
return Response(status=status.HTTP_400_BAD_REQUEST)
I'm having trouble incorporating pyPDF logic to merge two pdf files into my django site. I have written code that works to merge files when run in a python file on the local server(but I need to explicitly identify which files to merge:
from pyPdf import PdfFileReader, PdfFileWriter
output = PdfFileWriter()
input1 = PdfFileReader(file("abc_form0.pdf", "rb"))
input2 = PdfFileReader(file("abc_form1.pdf", "rb"))
total_pages = input1.getNumPages()
total_pages1 = input2.getNumPages()
for page in xrange(total_pages):
output.addPage(input1.getPage(page))
for page in xrange(total_pages1):
output.addPage(input2.getPage(page))
outputStream = file("output.pdf", "wb")
output.write(outputStream)
outputStream.close()
This code (from my django site) works to display a single PDF. However, when more than one PDF is selected, only the final PDF selected displays, hence the need to integrate pyPDF to create one file containing all requested files.
class ABCAdmin(admin.ModelAdmin):
actions = ['print_selected_pdf']
def create_pdf(self, request, queryset):
response = HttpResponse(mimetype="application/pdf")
response['Content-Disposition'] = 'attachment; filename=form.pdf'
for obj in queryset:
response.write(obj.form)
ABC.objects.filter(pk=obj.pk).update(user=request.user,pdf_printed="1",request_time=time.strftime("%H:%M:%S"),request_date=datetime.datetime.today())
return response
def print_selected_pdf(self, request, queryset):
# prints the pdfs for those that are selected,
# regardless if the pdf_printed field is true or false
qs = queryset.filter(pdf_printed__exact=0)
return self.create_pdf(request, qs)
I'm struggling with finding a way to combine these two methods. What I have tried is the following, but get an IO error [Errno 2] No such file or directory: 'obj.form'. So it is not reading in obj.form - I need to find a way for it to read in these objects correctly. Anyway, this is what I've tried.
def create_pdf(self, request, queryset):
response = HttpResponse(mimetype="application/pdf")
response['Content-Disposition'] = 'attachment; filename=form.pdf'
for obj in queryset:
output = PdfFileWriter()
input = PdfFileReader(file("obj.form","rb"))
total_pages = input.getNumPages()
for page in xrange(total_pages):
output.addPage(input.GetPage(page))
outputStream = file("output.pdf", "wb")
response.write(outputStream)
outputStream.close()
ABC.objects.filter(pk=obj.pk).update(user=request.user,pdf_printed="1",request_time=time.strftime("%H:%M:%S"),request_date=datetime.datetime.today())
return response
def print_selected_pdf(self, request, queryset):
# prints the pdfs for those that are selected,
# regardless if the pdf_printed field is true or false
qs = queryset.filter(pdf_printed__exact=0)
return self.create_pdf(request, qs)
As always, thanks for any help or tips you may be able to provide!
I used stringIO in the output stream to get around this. I also had to define each page of the PDF form to be added to the output. This works to iterate for any number of forms that I need to be requested.
def create_form(self, request, queryset):
response = HttpResponse(mimetype="application/pdf")
response['Content-Disposition'] = 'attachment; filename=form.pdf'
output = PdfFileWriter()
for obj in queryset:
input = PdfFileReader(cStringIO.StringIO(obj.form))
output.addPage(input.getPage(0))
output.addPage(input.getPage(1))
output.addPage(input.getPage(2))
output.addPage(input.getPage(3))
ABC_Self.objects.filter(pk=obj.pk).update(user=request.user,pdf_printed="1",request_time=time.strftime("%H:%M:%S"),request_date=datetime.datetime.today())
outputStream = cStringIO.StringIO()
output.write(outputStream)
response.write(outputStream.getvalue())
return response
All you need to do is provide the full absolute path to your PDF files, e.g.
/home/joseph/form.pdf
or
c:/home/joseph/form.pdf
etc.
I am uploading some .doc and .txt documents on my server, and i'd like to have two options:
-the user to be able to download the document
-the user to be able to read it online
i've read some code for the download function, but it doesn't seem to work.
my code:
def download_course(request, id):
course = Courses.objects.get(pk = id)
response = HttpResponse(mimetype='application/force-download')
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(/root/)
return response
def save_course(request, classname):
classroom = Classroom.objects.get(classname = classname)
if request.method == 'POST':
form = CoursesForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['course'])
new_obj = form.save(commit=False)
new_obj.creator = request.user
new_obj.classroom = classroom
new_obj.save()
return HttpResponseRedirect('.')
else:
form = CoursesForm()
return render_to_response('courses/new_course.html', {
'form': form,
},
context_instance=RequestContext(request))
def handle_uploaded_file(f):
destination = open('root', 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
any clue?
thanks!
You can open a File object to read the actual file, and then start download the file like this code:
path_to_file = os.path.realpath("random.xls")
f = open(path_to_file, 'r')
myfile = File(f)
response = HttpResponse(myfile, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=' + name
return response
path_to_file: is where the file is located on the server.
f = open(path_to_file, 'r') .. to read the file
the rest is to download the file.
Should the response['X-Sendfile'] be pointing to the file? It looks like it's only pointing at '/root/', which I'm guessing is just a directory. Maybe it should look more like this:
def download_course(request, id):
course = Courses.objects.get(pk = id)
path_to_file = get_path_to_course_download(course)
response = HttpResponse(mimetype='application/force-download')
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
return response
Where get_path_to_course_download returns the location of the download in the file system (ex: /path/to/where/handle_uploaded_files/saves/files/the_file.doc)