How to get only json value using jquery from calling an API? - python

The API returns both JSON and also render the template and when i call $.getJSON it will only return that render template but not JSON value. I have tried this
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/c.., summary=json.dumps(group))
but it says
bad request
Is there any way I can get that JSON value whenever I need it?
This is my view
#cms.route('/add/asset/<client_id>', methods=["GET"])
#login_required
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
if request.args['type'] == 'json':
return json.dumps(group)
else:
return render_template("/cms/asset_add.html", action="/add/asset", asset=None,
client_id=client_id,
types=Type.query.all())
else:
return 'permission denied'
and this is my ajax request
$(document).ready(function () {
$('#group_id').click(function () {
$.getJSON(
'/add/asset/' + {{ client_id }},
function (data) {
$('#group_id').find('option').remove();
var len = data.id.length;
for (var i = 0; i < len; i++) {
var option_item = '<option value="' + data.id[i] + '">' + data.name[i] + "</option>";
$('#group_id').append(option_item);
}
}
);
});
});

You can add parameter in html call to get the json result...
i.e)
const Endpoint = '/add/asset/?'
$.getJSON(Endpoint, {type: 'json'}).done(function(data...)

I believe this is what you are looking for
http://flask.pocoo.org/docs/0.12/api/#flask.Request.is_json
That is a flask method that checks if the request is json
Then you can use jsonify still in flask to return json (you need to import it though)
from flask import jsonify
so your code becomes
if request.is_json:
return jsonify(group)
Hope you find that useful and more elegant
One of the easier ways to debug is just return json alone for a start to see how the response looks in a browser. So you can remove login required (assuming you are not yet in production), do not check if the request is_json, then call the api and see what it returns. So assuming your client id is 1
#cms.route('/add/asset/<client_id>', methods=["GET"])
def asset_add(client_id):
if int(current_user.id_) == int(client_id):
group = {}
group['id'] = []
group['pid'] = []
group['name'] = []
for index in range(len([r.id_ for r in db.session.query(Assetgroup.id_)])):
for asset in (Assetgroup.query.filter_by(parent_id=(index or ''))):
group['id'].append(asset.id_)
group['pid'].append(asset.parent_id)
group['name'].append(asset.name)
return jsonify(group)
Now you can visit http://yoursite.com/add/asset/1 to see your response

Related

Issue in uploading image for prediction using a MultiPart POST Request

The call is currently happening via a Flutter application which makes a multi-part POST request.
Flutter Code
var request = http.MultipartRequest(
'POST',
Uri.parse('https://techfarmtest.herokuapp.com/upload'),
);
Map<String, String> headers = {"Content-type": "multipart/form-data"};
request.files.add(
http.MultipartFile(
widget.selectedImage.toString(),
widget.selectedImage.readAsBytes().asStream(),
widget.selectedImage.lengthSync(),
filename: widget.selectedImage.path.split('/').last,
),
);
request.headers.addAll(headers);
var res = await request.send();
http.Response response = await http.Response.fromStream(res);
var data = jsonDecode(response.body);
return data;
I intend to upload the image to the backend and then perform the prediction and retrieve the result in JSON format and the backend is scripted using Flask.
Flask Code
#app.route('/upload',methods=["POST"])
def upload_image():
if request.method == "POST":
imageFile = request.files['image']
fileName = werkzeug.utils.secure_filename(imageFile.filename)
print('\nRecieved File name : ' + imageFile.filename)
imageFile.save('./uploadedImages/' + fileName)
pred('./uploadedImages/fileName')
def pred(sampleFile):
model = load_model('./model.h5')
# model.summary()
sample_file = sampleFile
sample_img = image.load_img(sample_file,target_size = (256,256,3))
sample_img = image.img_to_array(sample_img)
sample_img = np.expand_dims(sample_img,axis=0)
prediction_arr = model.predict(sample_img)
result = {
'Sample' : str(sampleFile),
'Label' : str(class_names[prediction_arr.argmax()]),
'Confidence' : str(prediction_arr.max())
}
return jsonify(result)
The current issue I am facing is that I am making a bad request (400).This is a rough code (pseudocode) that I have figured out from various resources. Is there any way to go about it.
So, I figured it out by myself.
I will be attaching the code below for future references.
Flutter Code :
var request = http.MultipartRequest(
'POST',
Uri.parse('https://techfarmtest.herokuapp.com/upload'),
);
request.files.add(
await http.MultipartFile.fromPath('image', img.path),
);
var res = await request.send();
You can verify the POST request by using the below logs :
log('${res.statusCode}', name: 'POST-request-statusCode');
log('${res.reasonPhrase}', name: 'POST-request-status');
With respect to Flask :
#app.route('/upload',methods=["POST","PUT"])
def upload_image():
if request.method == "POST":
imageFile = request.files['image']
***you can perform any operation on the file you have recieved from the request now***
Thank you!

Flask request.files is always empty

I am making a POST request to send a JSON object with keys containing files. An example of what I send to the backend is:
export interface PosInputFiles {
org: string;
year_month: string;
in_master_file: File;
iv_file?: File;
sales_file?: File;
recv_file?: File;
transfer_file?: File;
adjust_file?: File;
pcount_file?: File;
gift_file?: File;
xrate?: string;
}
My POST request looks like:
generateMaster(args: PosInputFiles) {
return this.http.post('http://localhost:5000/api', args, { headers: this.headers});
}
When I try to access these files from request.json, the values are an empty dict ({}).
try:
org = request.json['org']
year_month = request.json['year_month']
in_master_file = request.json['in_master_file']
iv_file = None if 'iv_file' not in request.json else request.json['iv_file']
sales_file = None if 'sales_file' not in request.json else request.json['sales_file']
recv_file = None if 'recv_file' not in request.json else request.json['recv_file']
transfer_file = None if 'transfer_file' not in request.json else request.json['transfer_file']
adjust_file = None if 'adjust_file' not in request.json else request.json['adjust_file']
pcount_file = None if 'pcount_file' not in request.json else request.json['pcount_file']
gift_file = None if 'gift_file' not in request.json else request.json['gift_file']
xrate = None if 'xrate' not in request.json else request.json['xrate']
except:
return { "post" : "failed" }
print(in_master_file)
print(len(request.files))
return { "post": "success"}
Then I tried sending only one file and made sure len(request.json) == 0 through POSTMan and my frontend (Angular8). However, len(request.files) is also 0 and every time I try to access something, there is 400 error. My POST request is successful as I always print {"post", "success"} but for some reason, no files make it to the backend. All my files sent are real files and I have made sure that I am sending the file. Thank you so much for your help!
For those who might have the same problem eventually, here's how I solved this issue. Flask doesn't recognize files that aren't of FormData type so that's why I could only access JSON. Thus, I had to append all my files to a FormData variable.
generateMaster(submittedFiles: PosInputFiles) {
const formData: FormData = new FormData();
Object.keys(submittedFiles).forEach(key => {
if (submittedFiles[key] instanceof File) {
formData.append(key, submittedFiles[key], submittedFiles[key].name);
} else {
formData.append(key, new File([], submittedFiles[key]), submittedFiles[key].name);
}
})
return this.http.post('http://localhost:5000/api', formData, { headers: this.headers});
}
Then backend will finally recognize the files. In order to get other string data, and floats, I stored those values as the filename and could access them as such.
def post(self):
# Initilize arguments
org = request.files.get('org').filename
year_month = request.files.get('year_month').filename
in_master_file = request.files.get('in_master_file')
iv_file = request.files.get('iv_file')
sales_file = request.files.get('sales_file')
...
xrate = None if 'xrate' not in request.files else float(request.files.get('xrate').filename)

Can not read JSON returned array in Swift like Python enumerate

I am trying to replicate the following lines of python code from the https://github.com/joshfraser/robinhood-to-csv repo from GitHub in order to read my transaction history.
orders = robinhood.get_endpoint('orders')
paginated = True
page = 0
while paginated:
for i, order in enumerate(orders['results']):
executions = order['executions']
instrument = robinhood.get_custom_endpoint(order['instrument'])
fields[i + (page * 100)]['symbol'] = instrument['symbol']
for key, value in enumerate(order):
if value != "executions":
fields[i + (page * 100)][value] = order[value]
if order['state'] == "filled":
trade_count += 1
for key, value in enumerate(executions[0]):
fields[i + (page * 100)][value] = executions[0][value]
elif order['state'] == "queued":
queued_count += 1
# paginate
if orders['next'] is not None:
page = page + 1
orders = robinhood.get_custom_endpoint(str(orders['next']))
else:
paginated = False
Where we also have
def get_endpoint(self, endpoint=None):
res = self.session.get(self.endpoints[endpoint])
return json.loads(res.content.decode('utf-8'))
I have thus been working on the following iOS code. I work with this code in an XCode playground so feel free to make one to follow along
import UIKit
import PlaygroundSupport
let LoginEndpoint:String = "https://api.robinhood.com/api-token-auth/"
let LoginRequestData:[String : String] = ["username": "EmailAdress", "password": "Password"]
let OrdersEndpoint:String = "https://api.robinhood.com/orders/"
func httpReq(type: String, url: String, body:[String : String], header:[String : String]) -> ([String : Any]?, Data?, String?){
let url = URL(string: url)
var returnData:([String : Any]?, Data?, String?)? = nil
if let url = url {
var request = NSMutableURLRequest(url: url) as URLRequest
request.httpMethod = type
var postString = ""
for (key, value) in body {
if (postString != "") {
postString += "&"
}
postString += "\(key)=\(value)"
}
request.httpBody = postString.data(using: .utf8)
for (key, value) in header {
request.addValue(value, forHTTPHeaderField: key)
}
let _ = URLSession.shared.dataTask(with: request, completionHandler: {(data, response, error) in
if let data = data {
do {
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
returnData = (jsonSerialized, data, nil)
} catch (_) {
returnData = (nil, data, "JSON Parse Erro")
}
} else if let error = error {
returnData = (nil, nil, error.localizedDescription)
}
}).resume()
}
while (returnData == nil) {}
return returnData!
}
let tokenQuery = httpReq(type: "POST", url: LoginEndpoint, body: LoginRequestData, header: [:])
if let token = tokenQuery.0?["token"] {
print("token \(token)")
let historyQuery = httpReq(type: "GET", url: OrdersEndpoint, body: [:], header: ["Authorization": "Token \(token)"])
if let results = historyQuery.0?["results"], let countString = historyQuery.0?["count"] {
}
}
RunLoop.main.run()
PlaygroundPage.current.needsIndefiniteExecution = true
So as you can see I am using the auth token to get to the orders endpoint. I am indeed getting a good response from the orders endpoint but I have no clue how to interpret it.
It would seem from the python code that it is returning an array of JSON objects however I cant figure out how to get to that array in swift. I am not even sure if I am decoding it properly. The funny thing is when you look at the object returned in Playgrounds it would seem XCode knows that there is an array going on. How do I get to it?
Can't really get a good idea of the information being returned by your service, because of the lack of credentials.
However, check out SwiftyJSON. It's a really good library, and is extremely helpful with handling JSON data in Swift. It should solve your JSON handling issues.

Make table with returned values in jQuery takes 10x more time than call api in server

I'm trying to return results from themoviedb.com API. I measured that the whole python function takes 0.3s, but javascript makes table after 3-5s, how is it possible?
API call function in flask
def whispererSeries(partOfName):
# ODESLANI REQUEST NA API PRO ODPOVIDAJICI SERIALY
# API CALL
url = URL('https://api.themoviedb.org/3/search/tv?api_key=' + config['API_KEY'] + '&language=en-US&query=' + str(
partOfName) + '&page=1')
http = HTTPClient(url.host)
response = http.get(url.request_uri)
body = json.loads(response.read().decode('utf-8'))
if response.status_code == 200:
# VRACEJICI SE HODNOTA
# RETURN ARRAY OF DICTIONARIES
valToReturn = []
if (len(body['results']) > config['FIND_MAX_RESULTS']):
for i in range(config['FIND_MAX_RESULTS']):
valToReturn.append({
'Name': body['results'][i]['name'],
'Url': getUrlOfSerie(str(body['results'][i]['id']))
})
elif (len(body['results']) > 0):
for i in range(len(body['results'])):
valToReturn.append(body['results'][i]['name'])
else:
valToReturn = []
return jsonify(valToReturn)
else:
print('Error: %r') % (response.status_code)
And here in jQuery i call python function and append returned values to table.
// ODELSANI POZADAVKU NA SERVER
// CALL SERVER FUNCTION
$.ajax({
type: "POST",
contentType: 'application/json;charset=UTF-8',
// ODESLANI HODNOTY INPUTU
data: JSON.stringify($('.find-input').val()),
// CILOVA ADRESA
// ROUTE
url: '/indexWhisperer',
success: (response)=> {
console.log(response)
// VYCISTENI OD PREDCHOZICH VYSLEDKU
// CLEAR FROM PREVIOUS RESULTS
$('.founded-results tbody').empty()
// NASTAVENI VIDITELNOSTI TABULKY A PRIDANI VYSLEDKU
// MAKE TABLE VISIBLE AND APPEND RESULTS
response.forEach((item, index, array)=>{
$('.founded-results').css({'visibility': 'visible'})
$('.founded-results tbody').append('<tr><td><a href="' + item.Url + '">' + item.Name + '<a/></td></tr>');
})
},
error: (error)=>{
throw error
}
})
Just had made a MySQL database, inserted data from api and now it's a lot of faster.

JSON data not reaching view pyramid

I'm trying to build a page where when the user presses a button a variable which initially is 0 increments with 1. This number is then sent asynchronously to the server by using jQuery AJAX.
What I have so far is:
In my __init__.py file:
def main(global_config, **settings):
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind = engine)
Base.metadata.bind = engine
config = Configurator(settings = settings)
config.include('pyramid_jinja2')
config.add_static_view('static', 'static')
config.add_static_view('scripts', 'scripts')
# Removed the other views
config.add_route("declare_usage", '/user/{user_id}/{address_id}/declare')
config.add_route("declare_usage_json",'/user/{user_id}/{address_id}/declare.json')
config.scan()
My HTML + Jinja2:
#Removed code for simplicity
<div id="button_add">Add</div>
{{val}}
My JS:
$(document).ready(function(){
var room = 0;
jQuery.ajax({type:'POST',
url: '/user/1/5/declare', #I use a direct user ID and a direct address ID as I'm not sure how to send this to JS from Pyramid ... yet :).
data: JSON.stringify(room),
contentType: 'application/json; charset=utf-8'});
$('#button_add').click(function(){
room = room + 1;
});
});
My view code:
#view_config(route_name = 'declare_usage', renderer = 'declara.jinja2')
#view_config(route_name = 'declare_usage_json', renderer = 'json')
def declara_consum(request):
#Removed code for simplicity
val = request.POST.get('room') #I get a "None value in my html" if I change to request.json_body -> I get an error that there is no json to be parsed.
return { 'val' : val }
What happens is that when I open the debugger the POST request is successful with no data and on the page I get 2 options for 'val':
None -> When I use val = request.POST.get('room')
Error ValueError: No JSON object could be decoded -> When I use val = request.json_body
Also, still can't get it to work if in my JS i change url to be /user/1/5/declare.json and/or data to {'room' : room}
Can somebody please point out what I'm doing wrong?
you don't need another route declare_usage_json, just need separate two function like this
#view_config(route_name = 'declare_usage', renderer = 'declara.jinja2')
def declara_consum(request):
# this will response to your jinja2
return { 'val' : val }
#view_config(route_name = 'declare_usage', xhr=True, renderer = 'json')
def declara_consum_ajax(request):
# this will response to your asynchronously request
val = request.POST.get('room')
return { 'val' : val }
when you send a request using ajax, this will goto the second function.
$.ajax({
type: 'POST',
url: '/user/1/5/declare',
data: {'room' : room},
dataType: 'json'
}).done(function(response){
// update your data at html
});

Categories