How do I post a lot of data to Django? - python

I am trying to send of list of files to my Django Website. Each set is transmitted with the following info:
File name,
File size,
File location,
File type
Now, suppose I have 100 such sets of data, and I want to send it to my Django Website, what is the best method I Should use?
PS: I was thinking of using JSON, and then POST that JSON data to my Django URL. The data might then look like this:
{
"files": [
{ "filename":"Movie1" , "filesize":"702", "filelocation":"C:/", "filetype":"avi" },
{ "filename":"Movie2" , "filesize":"800", "filelocation":"C:/", "filetype":"avi" },
{ "filename":"Movie3" , "filesize":"900", "filelocation":"C:/", "filetype":"avi" }
]
}

I think sending json data to your server makes sense. Now to actually implement it, you would need your server to accept the http POST request that you will use to send the data about the files.
So, the server code may look like this:
urls.py:
import myapp
# ...
urlpatterns = patterns('', url(r'^json/$',myapp.serve_json), #http://<site_url>/json/ will accept your post requests, myapp is the app containing view functions
#add other urls
)
#other code
views.py
import json
def serve_json(request):
if request.method == 'POST':
if 'files' in request.POST:
file_list = json.loads(request.POST['files'])
for file in file_list:
#do something with each file dictionary in file_list
#...
return HttpResponse("Sample message") #You may return a message
raise Http404
Now in your Desktop application, once you have the list of the dictionaries of files, you may do this:
import urllib,json
data = urllib.urlencode({'files':json.dumps(file_dict)}) #file_dict has the list of stats about the files
response = urllib.urlopen('http://example.com/json/', data)
print response.read()
You may also look into urllib2 and httplib and use them in place of urllib.

Related

Python sending POST requests/ multipart/form-data

I'm just working on API conection at my work. I already made some GET and PUT request, but now i have problem with POST. API documantation is here. And here is my code I test but get 400 bad request:
import requests
files = {'files': ('fv.pdf', open(r"C:\python\API\fv.pdf", 'rb'))}
data = {"order_documents":[{'file_name':"fv.pdf", 'type_code':'CUSTOMER_INVOICE' }]}
header = {
'Authorization': '###########################',
}
response = requests.post("https://######.com/api/orders/40100476277994-A/documents", headers=header, files = files, data = data)
print(response.status_code)
print(response.url)
Someone have any idea how i can handle with this?
Looks like you are missing the order_documents parameter, it needs to be an array and also needs to be called order_documents.
Try changing your data variable into:
data = {"order_documents": [ {'file_name':"fv.pdf", 'type_code':'CUSTOMER_INVOICE' } ] }
The API expects files as the parameter name and your dictionary sends file to the server. The parameter name files that you give to session.post is just for requests library and not the actual parameter sent to the server.
The API also expects multiple files in an array, so you need to change your files object.
files = [
('files', ('fv.pdf', open(r"C:\python\API\fv.pdf", 'rb')),
]
Also, I don't think you need to use requests.Session(), just use requests.post(), unless you're planning on using the session object multiple times for subsequent requests.

Django - Serialize response from another server

I'm using DRF to make a GET request to another server and return this reponse to the client.
What I want to know is how do I get only selected fields from that other server's response to return to my client.
What I have is a response like this:
{
"plans": [
{
"setup_fee": 500,
"amount": 990,
"code": "plano01",
}
{
"setup_fee:...
"code": "plano02",
}...
An array with many objects. And I want to give to the client something like this:
{
"plans": [
{
"code": "plano01",
}
{"code": "plano02"...
Only the code field.
Whats the best way to do this with Django/DRF?
There's not much point in using DRF here. You're getting a response in JSON format, you just need to parse it to a dict, extract the elements you want, and return it back as JSON again; DRF would be overkill. The view can simply be:
def get_plan_codes(request):
data = requests.get('external_api...').json()
codes = [{'code': plan['code']} for plan in data['plans']]
data['plans'] = codes
return JsonResponse(data)
I don't think I would use DRF for this personally, although you could.
I think this could be done in a fairly straight foward way using just requests and django itself.
Something like:
from django.http import JsonResponse, HttpResponse
import json
import requests
def plans(request):
response = requests.get("my url for the request")
if response.status_code == 200:
json_content = json.loads(response.content)
# json_content is a python dictionary, so you can just postprocess the way you want it here
return JsonResponse(json_content)
else:
return #You will want to return an HttpResponse with the appropriate status code, see the docs below on that
# https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.HttpResponse.status_code

Trying to write a unit test for file upload to a django Restless API

I'm writing a fairly small lightweight REST api so I chose restless as the quickest/easiest support for that. I didn't seem to need all the complexity and support of the django-REST module. My service will only received and send json but users need to upload files to one single endpoint. Currently my view/api code for the file upload looks like:
class SubmissionCreate(Endpoint):
def post(self, request):
# get the data from the post request
data = {}
data['input_data'] = request.FILES['input_data'].read().decode('UTF-8')
data['submission_name'] = request.FILES['submission_name'].read().decode('UTF-8')
submission_form = SubmissionForm(data)
if submission_form.is_valid():
s = submission_form.save()
return {'message': 'file uploaded'}
else:
return {'error': 'Input information is not correctly formatted'}
I also wrote a small client with Requests to upload files
import os
import requests
import json
url = 'http://127.0.0.1:8000/submission/create/'
payload = {'input_data': ('input.txt', open('./static/files/file1.txt', 'rb')), 'submission_name': 'test'}
r = requests.post(url, files=payload)
This works great and I can push files to the database with my client. But obviously I want some proper testing before I give this any more complex behaviour, so I looked at the docs and wrote the following test
class SubmissionCreateTests(TestCase):
def test_submissioncreate_will_accept_data(self):
f = SimpleUploadedFile("file.txt", bytes("file_content", 'utf-8'))
response = self.client.post(reverse('submission_data'),
{'input_data': f, 'submission_name': 'test'})
self.assertEqual(response.status_code, 200)
However this produces the following error:
django.utils.datastructures.MultiValueDictKeyError: "'submission_name'"
If I set the content_type to 'application/x-www-form-urlencoded' I get the same error.
If I set the content_type to 'multipart/form-data' I get a 400 error but the tests run with no exception thrown.
I tried to fix this but in the end it was quicker and easier to switch to the Django-REST framework. The docs are so much better for Djano-REST that it was trivial to set it up and build tests. There seem to be no time savings to be had with regards either the restless or django-restless modules for django.

OkHttp upload multiple files with names to Python Flask server

At Server end I use Python flask:
from flask import Flask, request
app = Flask(__name__)
#app.route("/upload", methods=["POST"])
def upload():
print request.files
print request.form
return "200 ok"
if __name__ == '__main__':
app.run(port=5000)
Java test code block:
public void test_Upload() throws Exception{
MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
MediaType MEDIA_TYPE_XO = MediaType.parse("image/png");
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("/Users/lollipop/Downloads/ic_launch.png")))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"google\""),
RequestBody.create(MEDIA_TYPE_XO, new File("/Users/lollipop/Downloads/google-logo.png")))
.build();
Request request = new Request.Builder()
.url("http://localhost:5000/upload")
.post(requestBody)
.build();
Response resp = httpClient.newCall(request).execute();
System.out.println(resp.body().string());
}
And I run the test. server end cannot read the file from request.forms
output on server:
ImmutableMultiDict([])
ImmutableMultiDict([('image', u'5 ...many data ... fffd'), ('google', u'5i\u ...many data ... fffd'),('title', u'Square Logo')])
Why my files upload to request.form not in request.files. And all binary file data is parsed to unicode string.
Next, I test in Python requests. follows codes:
resp = requests.post("http://localhost:5000/upload",
files={
"image": open("/Users/lollipop/Downloads/ic_launch.png", "rb"),
"title": open("/Users/lollipop/Downloads/ic_launch.png", "rb"),
"google": open("/Users/lollipop/Downloads/google-logo.png", "rb")
})
And the server end output is reversed:
ImmutableMultiDict([('image', <FileStorage: u'ic_launch.png' (None)>), ('google', <FileStorage: u'google-logo.png' (None)>), ('title', <FileStorage: u'ic_launch.png' (None)>)])
ImmutableMultiDict([])
the upload files are in request.files not in request.form, this is my expected result.
So. how can I use OkHttp to upload files to flask server, and use request.files to retrive.
Update
the request is Flask requst.
from flask import request
the requests is a Python http client library.
This bug is not to Flask. I get misguided by this answer
At the OkHttp recipe in the documents. Described the post a file use the following code
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
Actually, this manner is not error, it post a file you don't need to provide a filename and other form data.
But this is not a usual usage.
We often need to upload a file with specified name and some key-value form data. We even need to upload more than one file.
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("username", username)
.addFormDataPart("password", password)
.addFormDataPart("avatar", "avatar.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.addFormDataPart("introduce_image", "introduce_image.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.build();

Include a pdf file in urls in Django

I've a pdf file in one of my main project directory. How should I add this file in the main urls.py file so as to link this file in <a href> tag.
EDIT
I get 2 dates, start and end date, via AJAX. I process the data b/w those 2 dates, generate a report and then returns an HttpResponse. The PDF report is now saved in my main project directory. Now I get a response back in AJAX. So, now how should I process the response in the success function, sent back from the sever and open a PDF file.
Thanks.
jQuery
$(function() {
$("#report_submit").click(function(){
$.ajax({
type : "POST",
url: "/reports/",
data : { 'start_date' : $("#startDate").val() , 'end_date' : $("#endDate").val() },
success : function(result){
},
error : function(result){
}
});
});
});
Django view code
def generate_report(request):
ctx = {}
if request.is_ajax():
if request.POST.has_key('start_date'):
start_date = datetime.strptime(request.POST[ 'start_date'] , '%m/%d/%Y')
end_date = datetime.strptime(request.POST[ 'end_date'] , '%m/%d/%Y')
......
# PDF GENERATED in MAIN PROJECT DIRECTORY
with open(os.path.join(os.path.dirname(__file__),'../../../../gui','Report.pdf')) as pdf:
response = HttpResponse(pdf.read(), content_type='application/pdf')
response['Content-Disposition'] = 'inline;filename=Report.pdf'
return response # so, now when I send a response back, how should I process it in AJAX success function?
pdf.closed
return render(request, 'generate_report/reports.html', ctx)
You can do this in two ways depending upon the requirements of your app
Add the pdf file to the static directory and serve it from there. After all pdf file is really just a static resource.
However, in case you need to do some checks before serving the file to the user eg. allowing only the authenticated users to access it, then write a view that will do the necessary checking and then serve the contents of the file with appropriate response headers. See example here
Edit after the OP updated their question
Is ajax absolutely necessary here? In case it is I can think of following:
Since you mention a report is being generated, I will assume that non authenticated and no authorized users shouldn't be able to access the report.
One way is to store the generated pdf file at some location (outside the static dir) and also save a record of the name of the generated file and the id of the user who can access it in a database table. The request can then simply respond with the name of the file.
In the success callback of ajax, open the url of a view along with the filename as get param in a separate tab. This view will check if the user can access the file and serve it.
Again, all this complexity can be avoided if ajax is not a requirement

Categories