Upload a file and json data in django restframework - python-3.x

I'm uploading a file and along with it I've few data fields to parse
json in restapi
views.py
class FileView(APIView):
def get(self,request):
#request.content_type= 'multipart/form-data;boundary=----WebKitFormBoundaryyrV7KO0BoCBuDbTL'
content = r'Submit File.'
return Response(content, status=status.HTTP_200_OK)
def post(self,request,*args,**kwargs):
try:
print(request.content_type)
print(request.data)
parser_classes =(MultiPartParser, JSONParser)
if not request.data.get('filename'):
content = "File is not uploaded !! Please upload a sample"
return Response(content, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
file = request.data.get('filename')
print(file)
request_Details = { }
request_Details['creator'] = request.data.get("creator", None)
request_Details['enable'] = request.data.get('enable', None)
request_Details['type'] = request.data.get('type', None)
request_Details['filename'] = request.data.get('filename')
requestsData = requests(filename=request_Details['filename'],creator=request_Details['creator'],enable=request_Details['enable'],type=request_Details['type'],)
requestsData.save()
content = "File submitted successfully"
return Response(content, status=status.HTTP_200_OK)
except Exception as exp:
logger.error("Exception in submitRequestView POST function ", exc_info=True)
content = {'Exception': 'Internal Error'}
return Response(content, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
model.py
class requests(models.Model):
id = models.AutoField(primary_key=True)
creator = models.CharField(max_length=255)
enable = models.CharField(max_length=255)
type = models.CharField(max_length=255)
filename = models.FileField(max_length=1000, null=True)
def __str__(self):
return self.id
serializer.py
class RequestsSerializer(serializers.ModelSerializer):
class Meta:
model = models.requests
fields = ('filename', 'creator', 'type', 'enable',)
urls.py
urlpatterns = [
#url(r'^admin/', admin.site.urls),
url(r'^File_upload/', views.FileView.as_view()),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)
setting.py(I've attached the media path code only)
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'#
My json request is as follows
{
"filename":"C://Users//Administrator//Desktop//file1.zip",
"creator":"aarav",
"enable":"yes",
"type":"dll"
}
and making use of media type as multipart/form-data not application/json , and MultipartParser and JsonParser classes in views.py.
I've tested my code from postman and I'm able to upload image to media folder and store the filename and other details in database.
Now when I try to POST from django restapi as shown in image attached , and I get the below error
Module : File_upload ERROR Exception in submitRequestView POST function
Traceback (most recent call last):
File "C:\Users\xxx\Desktop\fileupload\restapi_file\views.py", line 464, in post
print(request.data)
File "C:\Python27\lib\site-packages\rest_framework\request.py", line 212, in data
self._load_data_and_files()
File "C:\Python27\lib\site-packages\rest_framework\request.py", line 275, in _load_data_and_files
self._data, self._files = self._parse()
File "C:\Python27\lib\site-packages\rest_framework\request.py", line 350, in _parse
parsed = parser.parse(stream, media_type, self.parser_context)
File "C:\Python27\lib\site-packages\rest_framework\parsers.py", line 116, in parse
raise ParseError('Multipart form parse error - %s' % six.text_type(exc))
ParseError: Multipart form parse error - Invalid boundary in multipart: None
How to solve this and post request using restframework and not use any templates..??

Related

Flask restx multipart/form request with file and body with swagger

I am trying to implement, using flask-restx, an endpoint which will take both formData (a list of files to be more precise) and a body as json. My code looks as follow:
Multiple files param in some module:
def authorization_param(ns: Namespace, parser: Optional[RequestParser] = None) -> RequestParser:
if not parser:
parser = ns.parser()
parser.add_argument('Authorization', location='headers', required=False, default='Bearer ')
return parser
def multiple_file_param(arg_name: str, ns: Namespace, parser: Optional[RequestParser] = None) -> RequestParser:
if not parser:
parser = ns.parser()
parser.add_argument(arg_name, type=FileStorage, location='files', required=True, action='append')
return parser
Model:
some_form_model = api.model('form', {'field': fields.String())
And the endpoint itself:
ns = Namespace('sth', description='Some stuff'))
auth_param = authorization_param(ns=ns)
file_param = multiple_file_param(arg_name='File', ns=ns)
#ns.route('/files')
#ns.expect(auth_param)
class PreprocessFiles(Resource):
#ns.response(code=201, description='Job created', model=some_model)
#ns.response(code=400, description='Bad request', model=None)
#ns.response(code=401, description='Authentication Error', model=None)
#ns.response(code=403, description='Forbidden', model=None)
#ns.response(
code=422,
description='Input data validation Error',
model=some_model
)
#ns.expect(some_form_model)
#ns.expect(file_param)
def post(self):
payload = request.get_json()
# do some stuff..
return {'text': 'ok'}, 201
The endpoint is registered in an API object:
api.add_namespace(ns)
My problem is that in swagger I get either input body or file parameter, depending on the order of decorators I use. If I try to pass both form model and file param into one ns.expect as so
#ns.expect(some_form_model, file_param)
I get the following error in the console and the schema is not rendered:
2022-08-26 12:19:45.764 ERROR flask_restx.api api.__schema__: Unable to render schema
Traceback (most recent call last):
File "D:\Project\venv\lib\site-packages\flask_restx\api.py", line 571, in __schema__
self._schema = Swagger(self).as_dict()
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 239, in as_dict
serialized = self.serialize_resource(
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 446, in serialize_resource
path[method] = self.serialize_operation(doc, method)
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 469, in serialize_operation
if any(p["type"] == "file" for p in all_params):
File "D:\Project\venv\lib\site-packages\flask_restx\swagger.py", line 469, in <genexpr>
if any(p["type"] == "file" for p in all_params):
KeyError: 'type'
Is there any way to go around this? I would really like to have good swagger docs for the frontend folks.
Thanks in advance!
Best,
Mateusz

extract signature from SignatureField in Django

here i am using python3 and Django 3.0
Here am i saving the signature into my database and now i need to display this signature in my pdf file
But i am not able to display it in the pdf file
here is my views.py
def jobspecific_view_1(request, pk):
form = CustomerSignatureForm(request.POST or None)
if form.is_valid():
customer_signature_1 =
form.cleaned_data.get('customer_signature_1')
if customer_signature_1!=None:
job = AddJob.objects.get(id=pk)
job.customer_signature_1 = customer_signature_1
job.save()
......
......
here is my views.py for generating the pdf
def render_to_pdf(template_src, context_dict, pdf_title):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), result,
encoding='UTF-8')
if not pdf.err:
response = HttpResponse(result.getvalue(), content_type='application/pdf')
response['Content-Disposition'] = "attachment; filename={0}".format(
unidecode(
pdf_title.replace(
',', '').replace(
';', '').replace(' ', '_')))
logger.debug('Content-Disposition: {0}'.format(response['Content-Disposition']))
return response
logger.error(pdf.err)
return HttpResponse('We had some errors<pre>%s</pre>' % cgi.escape(html))
def generate_pdf_view(request, pk):
client = request.user.client
job_id = AddJob.objects.filter(id=pk)
viewed_job = get_object_or_404(AddJob, id=pk, created_by__client=client)
job_data={}
for val in job_id:
job_data['job_id'] = pk
job_data['title'] = val.title
job_data['job_number'] = val.job_number
job_data['customer_signature_1'] = val.customer_signature_1
......
......
pdf_title = u'{0}_{1}_{2}.pdf'.format(
job_data['title'], job_date.strftime('%d_%m_%Y'),
job_data['job_type'])
return render_to_pdf('jobs/jobpdf.html',
{
'pagesize':'A4', 'job_data': job_data,
'viewed_job': viewed_job,
'request': request,
}, pdf_title)
Here is my forms.py
class CustomerSignForm(forms.ModelForm):
customer_signature_1 = SignatureField(required=False,label="Customer Signature")
class Meta:
model = AddJob
fields = ['customer_signature_1']
Here is my jobspdf.html
<img src="data:image/png;base64,{{job_data.custmer_signature_1}}"/>
Please help me so that i can display the signature in my pdf view at present it not displaying anything in my pdf

Django throwing attribute error and i dont know why it is happening

I am trying to take image input from user in Django first the code was working fine but when I tried to run this code after a week it is giving me an attribute error and I don't why it is happening I tried to search on the internet but they only say it is because of the wrong syntax. The line, where the error arises, is file_type = file_type.lower() and line will be at last in the product_details function
views.py
from django.shortcuts import render
from django.http import HttpResponse
from datetime import datetime
from machine_website.models import contact_detail
from machine_website.models import product_data
from machine_website.forms import product_Form
# Create your views here.
def homepage(request):
descp1 = product_data()
descp1.disc = ' this is the discription'
descp1.img = '2.jpg'
descp2 = product_data()
descp2.disc = ' this is the discription 2'
descp2.img = '2.jpg'
descp3 = product_data()
descp3.disc = ' this is the discription 3'
descp3.img = '5.jpg'
descp = [descp1, descp2,descp3]
return render(request,'homepage.html', {'descp': descp})
def contact(request):
if request.method=="POST":
name = request.POST.get('name')
email = request.POST.get('email')
desc = request.POST.get('desc')
contact = contact_detail(name=name , email=email, desc=desc, date=datetime.today())
contact.save()
return render(request,'contact.html')
def services(request):
return render(request,'services.html')
def index(request):
return HttpResponse("this is index page")
def more(request):
info = product_data.objects.all()
return render(request ,'more.html' , {'info' : info})
IMAGE_FILE_TYPES = ['png' , 'PNG' , 'jpg' , 'JPG' , 'jpeg' , 'jfif']
def product_details(request):
form = product_Form()
if request.method == 'POST':
form = product_Form(request.POST, request.FILES)
if form.is_valid():
user_pr = form.save(commit=False)
user_pr.img = request.FILES['img']
file_type = user_pr.img.url.split('.')
file_type = file_type.lower()
if file_type not in IMAGE_FILE_TYPES:
return render(request, 'error.html')
user_pr.save()
return render(request, 'details.html', {'user_pr': user_pr})
context = {"form": form,}
return render(request, 'product_details.html', context)
TRACEBACk CALL
File "C:\Users\naveen\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\naveen\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\naveen\Desktop\cpp programs\first django project\machine_website\views.py", line 59, in product_details
file_type = file_type.lower()
AttributeError: 'list' object has no attribute 'lower'
[17/Apr/2021 17:00:46] "POST /product_details/ HTTP/1.1" 500 67315

Uploading images to a Flask API using FlaskClient

I have the following endpoint in my Flask API:
#api.route("/files", methods=Method.POST)
def upload_file() -> str:
enquirer_id = request.get_json()['id']
try:
logging.info(request.files)
uploaded_file = request.files['image']
except KeyError:
abort(HttpStatusCode.BAD_REQUEST, "Please provide image to upload")
if uploaded_file.content_type != ContentType.JPEG:
abort(HttpStatusCode.BAD_REQUEST, "Only JPEG images are allowed")
filename = str(enquirer_id)
destination_file = os.path.join(current_app.config[AppCfg.DIRECTORY], filename)
uploaded_file.save(destination_file)
return f'Successfully upload file {filename}.'
But I am unable to test this endpoint using the FlaskClient:
class APITestUploadDownload(APITestBase):
url = '/api/v1/files'
my_file = 'some_picture.jpg'
def setUp(self):
self.client = self.app.test_client()
def test_upload(self):
with open(file=self.my_file, mode='rb') as file:
data = {
'image': io.BytesIO(file.read()),
'id': 1
}
response = self.client.post(self.url, data=json.dumps(data), headers={}, content_type='multipart/form-data',)
self.assertEqual(response.status_code, HttpStatusCode.OK)
But this fails with the error message TypeError: Object of type BytesIO is not JSON serializable.
If i make the request without using json.dump(data) using response = self.client.post(self.url, data=data, headers={}, content_type='multipart/form-data', ) I get another error which tells me thatresponse.data is None.
So how can I fix my file upload endpoint and the correspondig test?

AttributeError: 'tuple' object has no attribute 'get' Django

I'm a beginner learning django i've checked multiple times but didn't find out where its returning tuple instead of dictionary can anyone help.
forms.py
from django import forms
from .models import ModelClas
class FormClass(forms.ModelForm):
passw = forms.CharField(widget=forms.PasswordInput())
repass = forms.CharField(widget=forms.PasswordInput())
def clean(self):
super(FormClass, self).clean()
inputpass = self.cleaned_data.get('passw')
inputrepass = self.cleaned_data.get('repass')
if inputpass != inputrepass:
raise forms.ValidationError("Password not matched. please type again.")
return inputpass, inputrepass
class Meta:
model = ModelClas
fields = '__all__'
models.py
from django.db import models
# Create your models here.
class ModelClas(models.Model):
fname = models.CharField(max_length=30)
lname = models.CharField(max_length=30)
email = models.EmailField()
mobile = models.IntegerField()
passw = models.CharField(max_length=30)
repass = models.CharField(max_length=30)
views.py
def signpage(request):
if request.method == 'GET':
form = forms.FormClass()
if request.method == 'POST':
form = forms.FormClass(request.POST)
if form.is_valid():
print("Validation Successfull")
print("FName :", form.cleaned_data['fname'])
print("LName :", form.cleaned_data['lname'])
print("Email :", form.cleaned_data['email'])
print("Mobile :", form.cleaned_data['mobile'])
print("Password :", form.cleaned_data['passw'])
print("Re-type Password :", form.cleaned_data['repass'])
form.save(commit=True)
return HttpResponseRedirect('/accounts/logout')
return render(request, 'registration/signup.html', {'form':form})
The error.
Even understanding this error is really daunting for me if anyone explain it would be great
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/signup/
Django Version: 3.0.6
Python Version: 3.6.8
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'UserRegis']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "/home/ashish/.local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ashish/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ashish/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ashish/DjangoProjects/Django/userd/UserRegis/views.py", line 26, in signpage
if form.is_valid():
File "/home/ashish/.local/lib/python3.6/site-packages/django/forms/forms.py", line 180, in is_valid
return self.is_bound and not self.errors
File "/home/ashish/.local/lib/python3.6/site-packages/django/forms/forms.py", line 175, in errors
self.full_clean()
File "/home/ashish/.local/lib/python3.6/site-packages/django/forms/forms.py", line 378, in full_clean
self._post_clean()
File "/home/ashish/.local/lib/python3.6/site-packages/django/forms/models.py", line 385, in _post_clean
exclude = self._get_validation_exclusions()
File "/home/ashish/.local/lib/python3.6/site-packages/django/forms/models.py", line 345, in _get_validation_exclusions
field_value = self.cleaned_data.get(field)
Exception Type: AttributeError at /signup/
Exception Value: 'tuple' object has no attribute 'get'
The error is in the data returned by your method FormClass.clean(). The method should return a dict with the form fields as keys or not return anything at all (which is an implicit return None).
More info: https://docs.djangoproject.com/en/2.2/ref/forms/validation/#validating-fields-with-clean
My suggestion is to just remove the return statement from the method:
class FormClass(forms.ModelForm):
...
def clean(self):
super().clean()
inputpass = self.cleaned_data.get('passw')
inputrepass = self.cleaned_data.get('repass')
if inputpass != inputrepass:
raise forms.ValidationError("Password not matched. please type again.")
That should solve your error.
In this line you're returning a tuple consisting of your inputpass and inputrepass. Why?
return inputpass, inputrepass
You should return cleaned_data instead:
class FormClass(forms.ModelForm):
passw = forms.CharField(widget=forms.PasswordInput())
repass = forms.CharField(widget=forms.PasswordInput())
def clean(self):
super(FormClass, self).clean()
inputpass = self.cleaned_data.get('passw')
inputrepass = self.cleaned_data.get('repass')
if inputpass != inputrepass:
raise forms.ValidationError("Password not matched. please type again.")
return self.cleaned_data #**FIX HERE**
class Meta:
model = ModelClass
fields = '__all__'

Resources