pdfkit django in digitalocean - django

pdfkit works in the local machine everything works successfully displays as pdf, but in digitalocean sends to the server error 500, why?
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.template.loader import get_template
import pdfkit
from .models import Buses
def pdf(request, id):
bus = Buses.objects.get(id=id)
template = get_template('buses/pdf.html')
html = template.render({'bus': bus})
options = {
'page-size': 'Letter',
'encoding': "UTF-8",
}
pdf = pdfkit.from_string(html, False, options)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="{}_{}.pdf"'.format(bus.company, bus.name)
return response

If your template references other files, you may need to set 'enable-local-file-access': True in your options.
See: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/4460

I am not sure but your problem could be the location of wkhtmltopdf
It is always a better option to specify the wkhtmltopdf location. So on your digital ocean server - start by installing wkhtmltopdf - if you dont have it yet.
This is a great tutorial to use for any version of Ubuntu - https://computingforgeeks.com/install-wkhtmltopdf-on-ubuntu-debian-linux/
Then on your command line:
which wkhtmltopdf
Note the location, your code will then look like this:
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.template.loader import get_template
import pdfkit
from .models import Buses
def pdf(request, id):
bus = Buses.objects.get(id=id)
template = get_template('buses/pdf.html')
html = template.render({'bus': bus})
options = {
'page-size': 'Letter',
'encoding': "UTF-8",
}
config = pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf') #use your actual location here
pdf = pdfkit.from_string(html, False, configuration=config, options=options)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="{}_{}.pdf"'.format(bus.company, bus.name)
return response

Related

flask_uploads Can Not Find Destination For Images

What I'm basically trying to do is use flask_uploads to find the path for an uploaded photo. I'm getting 'RuntimeError: no destination for set images' whenever I run the code. I've been over about 10 different tutorials and have gone over the code about 50 times. Please, for my sanity, help me out.
Here's my code
from colorthief import ColorThief
import matplotlib.pyplot as plt
from flask_uploads import configure_uploads, IMAGES, UploadSet
from flask import Flask, render_template, redirect, url_for, request
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, FileField
import os
class InsertPic(FlaskForm):
image = FileField('Select Your Picture')
URL = 'D:\Python Porfolio\Colors\static\images'
app = Flask(__name__)
app.config['SECRET_KEY'] = '8BYkEfBA6O6donzWlSihBXox7C0sKR6b'
app.config['UPLOADED_PHOTOS_DEST'] = 'static/images'
Bootstrap(app)
images = UploadSet('images', IMAGES)
configure_uploads(app, images)
#app.route('/', methods=['GET', 'POST'])
def index():
form = InsertPic()
if form.validate_on_submit():
filename = images.save(form.image.data)
file_url = images.url(filename)
ct = ColorThief(f"{file_url}")
colors = ct.get_palette(color_count=11)
plt.imshow([[colors[a] for a in range(10)]])
plt.axis('off')
plt.savefig("output.jpg", bbox_inches='tight', pad_inches=0)
# Convet to HEX Values
separate_colors = []
for color in colors:
a = f"#{color[0]:02x}{color[1]:02x}{color[0]:02x}"
separate_colors.append(a)
return render_template('colors.html', colors=separate_colors)
return render_template('index.html', form=form)
if __name__ == "__main__":
app.run(debug=True)
Here's my Traceback info:
File "D:\prjects\pythonProject3\main.py", line 23, in <module>
configure_uploads(app, images)
File "D:\prjects\pythonProject3\venv\lib\site-packages\flask_uploads\flask_uploads.py", line 122, in configure_uploads
config = config_for_set(uset, app, defaults)
File "D:\prjects\pythonProject3\venv\lib\site-packages\flask_uploads\flask_uploads.py", line 84, in config_for_set
raise RuntimeError("no destination for set %s" % uset.name)
RuntimeError: no destination for set images

How to upload file on Django REST endpoint quickly?

I am using Django REST framework to upload a large csv file and extract the data from the file and save the data in the data. By large file I mean file of like 10 to 50mb but when I upload a file its taking way longer then expected like 10 to 15mins but the endpoint keeps on processing and does not returns the response here is how my views.py looks like:
from asyncore import read
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.response import Response
import pandas as pd
from .models import ExtractedData
from .urls import urlpatterns
from django.urls import path
# Create your views here.
class FileUploadView(APIView):
parser_classes = ( MultiPartParser, FormParser)
def put(self, request, format=None):
file_obj = request.FILES['file']
df = pd.read_csv(file_obj)
dict_data = df.to_dict(orient='records')
for dict in dict_data:
ExtractedData.objects.get_or_create(data=dict)
return Response({'details':"File Saved Succesfully"}, status=204)

django api throwing 500(internal server) error with connection to mysql

I get 500(Internal Server Error) for the below code, cant able to identify the problem. Please help me
urls.py
from django.conf.urls import url
from .audfile import daywisedetail,hourwisedetail
urlpatterns = [
url(r'^pyapi/api/daywise/(?P<start_date>[\w-]+)/(?P<end_date>[\w-]+)/$',daywisedetail.as_view()),
url(r'^pyapi/api/hourwise/(?P<start_date_val>[\w-]+)/(?P<end_date_val>[\w-]+)/$',hourwisedetail.as_view()),
]
audfile.py
from rest_framework.views import APIView
from django.http import JsonResponse
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import View
from django.template.loader import get_template
from rest_framework.response import Response
from rest_framework import status
import MySQLdb
sdatabase = MySQLdb.connect(host="localhost",user="root",passwd="password",db="main")
class daywisedetail(APIView):
def get(self,request,start_date=None,end_date=None,format=None):
db = sdatabase
cursor = db.cursor()
daydetail = """select id, values, name, email from day_users where date(reg_date) between '%s' and '%s' """ % (start_date,end_date)
cursor.execute(daydetail)
getdaydetailresult = cursor.fetchall()
mainlist=[]
for v0 in getdaydetailresult:
for v1 in v0:
mainlist.append(v1)
data = {
"hours": mainlist
}
return Response(data)
class hourwisedetail(APIView):
def get(self,request,start_date_val=None,end_date_val=None,format=None):
db = sdatabase
cursor = db.cursor()
hourwisedata = """select id, values, name, email from hour_users where date(reg_date) between '%s' and '%s' """ % (start_date_val,end_date_val)
cursor.execute(hourwisedata)
hourwisedataresult = cursor.fetchall()
mainlist1=[]
for v2 in hourwisedataresult:
for v3 in v2:
mainlist1.append(v3)
data1 = {
"days": mainlist1
}
return Response(data1)
If i have single class(daywisedetail), api is working properly, if i am adding second class(hourwisedetail), both the apis are showning 500 responce.
cant able to find where is the bug, please help me.

how to show pdf from server in a Django view?

I am trying to show/read pdfs from server , but getting erros. Below I have attached my view.py . Please help me to solve it
views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import PDF
def pdf_view(request):
a = PDF.objects.get(id=id)
with open('a.pdf', 'rb') as pdf:
response = HttpResponse(pdf.read(), contenttype='application/pdf')
response['Content-Disposition'] = 'filename=a.pdf'
return response
pdf.closed
you can use use Django templates to show/read pdf on sever. create 'templates' folder inside your django project. inside it create a html file which contain link of you pdf.

How to generate a file upload (test) request with Django REST Framework's APIRequestFactory?

I have developed an API (Python 3.5, Django 1.10, DRF 3.4.2) that uploads a video file to my media path when I request it from my UI. That part is working fine. I try to write a test for this feature but cannot get it to run successfully.
#views.py
import os
from rest_framework import views, parsers, response
from django.conf import settings
class FileUploadView(views.APIView):
parser_classes = (parsers.FileUploadParser,)
def put(self, request, filename):
file = request.data['file']
handle_uploaded_file(file, filename)
return response.Response(status=204)
def handle_uploaded_file(file, filename):
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
if not os.path.exists(dir_name):
os.makedirs(dir_name)
file_path = os.path.join(dir_name, new_filename)
with open(file_path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
and
#test.py
import tempfile
import os
from django.test import TestCase
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from rest_framework.test import APIRequestFactory
from myapp.views import FileUploadView
class UploadVideoTestCase(TestCase):
def setUp(self):
settings.MEDIA_ROOT = tempfile.mkdtemp(suffix=None, prefix=None, dir=None)
def test_video_uploaded(self):
"""Video uploaded"""
filename = 'vid'
file = File(open('media/testfiles/vid.mp4', 'rb'))
uploaded_file = SimpleUploadedFile(filename, file.read(), 'video')
factory = APIRequestFactory()
request = factory.put('file_upload/'+filename,
{'file': uploaded_file}, format='multipart')
view = FileUploadView.as_view()
response = view(request, filename)
print(response)
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
file_path = os.path.join(dir_name, new_filename)
self.assertTrue(os.path.exists(file_path))
In this test, I need to use an existing video file ('media/testfiles/vid.mp4') and upload it since I need to test some processings on the video data after: that's why I reset the MEDIA_ROOT using mkdtemp.
The test fails since the file is not uploaded. In the def put of my views.py, when I print request I get <rest_framework.request.Request object at 0x10f25f048> and when I print request.data I get nothing. But if I remove the FileUploadParser in my view and use request = factory.put('file_upload/' + filename, {'filename': filename}, format="multipart") in my test, I get <QueryDict: {'filename': ['vid']}> when I print request.data.
So my conclusion is that the request I generate with APIRequestFactory is incorrect. The FileUploadParseris not able to retrieve the raw file from it.
Hence my question: How to generate a file upload (test) request with Django REST Framework's APIRequestFactory?
Several people have asked questions close to this one on SO but I had no success with the proposed answers.
Any help on that matter will be much appreciated!
It's alright now! Switching from APIRequestFactory to APIClient, I managed to have my test running.
My new test.py:
import os
import tempfile
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from django.contrib.auth.models import User
class UploadVideoTestCase(APITestCase):
def setUp(self):
settings.MEDIA_ROOT = tempfile.mkdtemp()
User.objects.create_user('michel')
def test_video_uploaded(self):
"""Video uploaded"""
filename = 'vid'
file = File(open('media/testfiles/vid.mp4', 'rb'))
uploaded_file = SimpleUploadedFile(filename, file.read(),
content_type='multipart/form-data')
client = APIClient()
user = User.objects.get(username='michel')
client.force_authenticate(user=user)
url = reverse('file_upload:upload_view', kwargs={'filename': filename})
client.put(url, {'file': uploaded_file}, format='multipart')
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
file_path = os.path.join(dir_name, new_filename)
self.assertTrue(os.path.exists(file_path))
Below, testing file upload using APIRequestFactory as requested (and ModelViewSet).
from rest_framework.test import APIRequestFactory, APITestCase
from my_project.api.views import MyViewSet
from io import BytesIO
class MyTestCase(APITestCase):
def setUp(self):
fd = BytesIO(b'Test File content') # in-memory file to upload
fd.seek(0) # not needed here, but to remember after writing to fd
reqfactory = APIRequestFactory() # initialize in setUp if used by more tests
view = MyViewSet({'post': 'create'}) # for ViewSet {action:method} needed, for View, not.
request = factory.post('/api/new_file/',
{
"title": 'test file',
"fits_file": self.fd,
},
format='multipart') # multipart is default, but for clarification that not json
response = view(request)
response.render()
self.assertEqual(response.status_code, 201)
Note that there is no authorization for clarity, as with: 'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'].