How do i pass a form data as context? - django

I have this PDFview class now i want to use it in any form template so i can see preview of that form data before sending data.
class PDFView(View):
def get(self, request, **kwargs):
template = get_template("pim/pdfview.html")
ctx = {}
ctx["test"] = Employee.objects.all()
context = Context(ctx)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
response = http.HttpResponse(result.getvalue(), mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename="leavereport.pdf"'
return response
return http.HttpResponse('We had some errors<pre>%s</pre>' % cgi.escape(html))

Related

DRF not supporting multiple renderer_classes

I'm using Django 2.x and DRF
I have a view which returns the binary data in different formats like pdf, eps, etc.
To return binary response, I have set the renderer_classes property and my view is
class DownloadQRCode(APIView):
renderer_classes = (PdfFileRenderer, EPSRenderer,)
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
name = serializer.validated_data.get('name')
data = serializer.validated_data.get('data')
mimetype = None
if data and name:
imgarr = name.rsplit('.', 1)
if len(imgarr) == 2:
name, format = imgarr
if format == 'pdf':
data = str(unquote(data, encoding='utf-8'))
data, mimetype = generate_data_cairo(data, format)
if format == 'eps':
data = str(unquote(data, encoding='utf-8'))
data, mimetype = svg_2_eps(data)
if data and mimetype:
response = Response(data=data, content_type=mimetype)
response['Content-Disposition'] = 'attachment; filename=%s' % "-".join(name.split())
return response
else:
return Response(status=status.HTTP_400_BAD_REQUEST, data='Either data or mime type was missing')
else:
return Response(status=status.HTTP_400_BAD_REQUEST, data='filename does not contain formatInfo')
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
I have two renderer_classes
PdfFileRenderer
class PdfFileRenderer(BaseRenderer):
media_type = 'application/octet-stream'
format = None
charset = None
render_style = 'binary'
def render(self, data, media_type=None, renderer_context=None):
return data
and EPSRenderer
class EPSRenderer(BaseRenderer):
media_type = 'image/eps'
format = None
charset = 'utf-8'
render_style = 'binary'
def render(self, data, accepted_media_type=None, renderer_context=None):
return data
Using any one of them is working fine for that file type. But I want to use both so that appropriate renderer can be used depending on the file requested.
But, this is giving error and only first in the set is working.
Agree with #Nafees
Got it resolved by overriding get_renderer() method.
def get_renderer(self):
imgarr = name.rsplit('.', 1)
name, format = imgarr
if format == 'pdf':
return [BinaryRenderer()]
if format == 'eps':
return [EPSRenderer()]
return super().get_renderer()

Django CBV : Download PDF document from media

I would like to download pdf file in my view but I don't overcome to display browser window which let to download my file.
The downloadPDF function seems to work well but nothing appears on my browser.
This is my class :
class TokenDownloadView(TemplateView):
template_name = 'app/token.html'
def get_context_data(self, **kwargs):
now = timezone.now()
context = super().get_context_data(**kwargs)
context['token'] = self.kwargs['token']
token = context['token']
download = Download.objects.get(token__iexact=token)
upload_doc = Document.objects.get(id=download.pub_id).upload
if download and download.expiration_date > now:
print("token valide jusqu'à : " + str(download.expiration_date))
print("il est actuellement : " + str(now))
print(' ==> Token existe et valide <==')
messages.success(self.request, 'Vous allez télécharger le document')
self.downloadPDF(upload_doc)
if download and download.expiration_date < now:
print("token valide jusqu'à : " + str(download.expiration_date))
print("il est actuellement : " + str(now))
print('==> Token existe mais a expiré <==')
messages.error(self.request, 'Document non téléchargé : la session a expiré')
return context
def downloadPDF(self, upload_doc):
from django.core.files.storage import FileSystemStorage
from django.http import HttpResponse, HttpResponseNotFound
fs = FileSystemStorage()
filename = upload_doc
if fs.exists(filename):
with fs.open(filename) as pdf:
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="mypdf.pdf"'
return response
else:
return HttpResponseNotFound('The requested pdf was not found in our server.')
I miss something in my class which could let to download my pdf ?
EDIT :
I edited my class in order to convert get_context_data() to get() method. It seems to work but I would like to get your mind :
class TokenDownloadView(TemplateView):
template_name = 'app/token.html'
def get(self, request, *args, **kwargs):
now = timezone.now()
context = super().get(request, *args, **kwargs)
token = self.kwargs['token']
download = Download.objects.get(token__iexact=token)
document_title = Document.objects.get(id=download.pub_id).title
upload_doc = Document.objects.get(id=download.pub_id).upload
if download and download.expiration_date > now:
print("Token is valid until : " + str(download.expiration_date))
print("Now : " + str(now))
print(' ==> Token exists and valid <==')
messages.success(self.request, 'You are going to download document(s)')
resp = self.downloadPDF(upload_doc, document_title)
if download and download.expiration_date < now:
print("Token is valid until : " + str(download.expiration_date))
print("Now : " + str(now))
print('==> Token exists but has expired <==')
messages.error(self.request, 'Session of 10 minutes has expired - Please download document(s) one more time')
return render(request, self.template_name)
return resp
def downloadPDF(self, upload_doc, document_title):
fs = FileSystemStorage()
filename = upload_doc
if fs.exists(filename):
with fs.open(filename) as pdf:
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % document_title
return response
else:
return HttpResponseNotFound('The requested pdf was not found in our server.')
You call the downloadPDF but you ignore its return value. You would need to return the result of calling that method. However, this will not work because you cannot return a response from get_context_data; that method, as the name implies, must return a dictionary context and not a response.
You need to move this code into the get method.

Django throws internal 500 error while saving heavy data in session variable

I am trying to filter some values and holding these values in session variable for writing these values in a excel sheet and also for endless pagination.Some times the query set values reaches nearly 55000.that time django shows internal server error.
views.py
def search(request,template='admin/search.html', page_template='pagination/paginate_student.html'):
rg = request.POST.get
skill = rg('skills')
students_list = []
ec_students = EcStudentProfile.objects.filter(Q(Technical_skills__icontains=skill))
cs_students= CsStudentProfile.objects.filter(Q(jobrole__icontains=skill))
me_students = MeStudentProfile.objects.filter(
Q(jobrole__icontains=skill))
results = list(chain(ec_students, cs_students, me_students))
for result in results:
students_list.append(result)
if students_list:
request.session['list'] = students_list
students_list = request.session['list']
if 'excel' in request.POST:
students_list = request.session['list']
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=Report.xlsx'
xlsx_data = WriteToExcel(students_list)
response.write(xlsx_data)
return response
if request.is_ajax():
students_list = request.session['list']
template = page_template
return render_to_response(template,
{'page_template': page_template, 'students_list': students_list}, context_instance=RequestContext(request))

download a file after rendering a template in django

I am trying to download a csv file and rendering a template at the same time after redirecting from a view but it only downloads the file ,doesn't render the template.
I think it can be handled by middleware but finding an easier solution to it.
class ProductUploadView(FormView):
template_name ='upload.html'
form_class = csvform
success_url = 'response/'
failed_rows = []
def post(self,request,*args,**kwargs):
form = self.form_class(request.POST,request.FILES)
file = request.FILES['csvfile']
csvfile = csv.reader(utf_8_encoder(file), dialect='excel', delimiter=',')
csvfile.next()
for row in csvfile:
if row[1] in ['PRES','GEN','GEN'] and row[2] in ['CAPS','TAB','SYP','GEL','SUSP','INJ']:
try:
p, created = Product.objects.get_or_create(brand_name=row[0], category=row[1], defaults={'form': row[2], 'mrp': row[3], 'ptr': row[4]})
except ValidationError:
self.failed_rows.append(row)
pass
else:
self.failed_rows.append(row)
return HttpResponseRedirect(self.success_url)
class UploadedView(ProductUploadView):
template_name = 'response.html'
rows = ProductUploadView.failed_rows
def download_view(self,request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
writer = csv.writer(response)
writer.writerows(self.rows)
return response
def get(self,request):
response = TemplateResponse(request,self.template_name,{'num':len(self.rows),'failed_rows':self.rows})
response.add_post_render_callback(download_view)
return response

Django - VIew didn't return an HttpResponse Object even though HttpResponse returns

The error I am getting:
The view report.views.csv_gen_universal didn't return an HttpResponse object.
def csv_gen_universal(req):
if req.POST['csvinputid']:
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] ='attachment;filename="M_Wall_report.csv"'
writer = csv.writer(response)
content = str(req.POST['csvinputid']).split("^~^")
for m in content :
p = m.split("*~*")
writer.writerow(p)
return response
else:
HttpResponse("Wrong Place")
You forgot to add return in your else statement. Your code should be
def csv_gen_universal(req):
if req.POST['csvinputid']:
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] ='attachment;filename="M_Wall_report.csv"'
writer = csv.writer(response)
content = str(req.POST['csvinputid']).split("^~^")
for m in content :
p = m.split("*~*")
writer.writerow(p)
return response
else:
return HttpResponse("Wrong Place")