Calling a python function using dojo/request - python

Firstly, I'm very new to the world of web development, so sorry if this question is overly simple. I'm trying to use python to handle AJAX requests. From reading the documentation it seems as though Dojo/request should be able to do this form me, however I've not found any examples to help get this working.
Assuming I've got a Python file (myFuncs.py) with some functions that return JSON data that I want to get from the server. For this call I'm interested in a particular function inside this file:
def sayhello():
return simplejson.dumps({'message':'Hello from python world'})
What is not clear to me is how to call this function using Dojo/request. The documentation suggests something like this:
require(["dojo/dom", "dojo/request", "dojo/json", "dojo/domReady!"],
function(dom, request, JSON){
// Results will be displayed in resultDiv
var resultDiv = dom.byId("resultDiv");
// Request the JSON data from the server
request.get("../myFuncs.py", {
// Parse data from JSON to a JavaScript object
handleAs: "json"
}).then(function(data){
// Display the data sent from the server
resultDiv.innerHTML = data.message
},
function(error){
// Display the error returned
resultDiv.innerHTML = error;
});
}
);
Is this even close to what I'm trying to achieve? I don't understand how to specify which function to call inside myFuncs.py?

What you could also do is to create a small jsonrpc server and use dojo to do a ajax call to that server and get the json data....
for python side you can follow this
jsonrpclib
for dojo you could try something like this..
<script>
require(['dojox/rpc/Service','dojox/rpc/JsonRPC'],
function(Service,JsonRpc)
{
function refreshContent(){
var methodParams = {
envelope: "JSON-RPC-2.0",
transport: "POST",
target: "/jsonrpc",
contentType: "application/json-rpc",
services:{}
};
methodParams.services['myfunction'] = { parameters: [] };
service = new Service(methodParams);
function getjson(){
dojo.xhrGet({
url: "/jsonrpc",
load : function(){
var data_list = [];
service.myfunction().then(
function(data){
dojo.forEach(data, function(dat){
data_list.push(dat);
});
console.log(data_list)
},
function(error) {
console.log(error);
}
);
}
});
}
getjson();
}
refreshContent();
});
});
</script>
I've used this approach with django where i am not creating a different server for the rpc calls but using django's url link to forward the call to my function.. But you can always create a small rpc server to do the same..

Related

React Native + Django DRF network error on POST

I'm developing a React Native app. As a backend I'm using DJango DRF. I'm trying to make POST request for creating a new element on backend, this is my code in React:
**API.JS**
const routes = {
accounts: {
get: () =>
requestHelper({
method: "get",
url: "accounts/",
}),
post: (data) =>
requestHelper({
data,
method: "post",
url: "accounts/",
}),
},
};
**API CALL**
const formData = new FormData();
const image = {
uri: data.image,
name: data.timestamp + ".jpg",
type: "image/jpeg",
};
_.map(data, (item, name) => {
formData.append(name, item);
});
formData.append("image", image);
await api.accounts
.post(formData)
.then((res) => {
console.log(res, "OK");
})
.catch((err) => {
console.log(err);
});
};
Te request is reaching backend and the new Account is being created on database (including the image). The problem is that,despite that Django is returning 200_OK, the api call is going to the catch statement, and this error appears on console:
Network Error
Stack trace: node_modules/axios/lib/core/createError.js:15:0 in
node_modules/axios/lib/adapters/xhr.js:81:4 in
dispatchXhrRequest
node_modules/event-target-shim/dist/event-target-shim.js:818:20 in
EventTarget.prototype.dispatchEvent
node_modules/react-native/Libraries/Network/XMLHttpRequest.js:575:10
in setReadyState
node_modules/react-native/Libraries/Network/XMLHttpRequest.js:389:6 in
__didCompleteResponse node_modules/react-native/Libraries/vendor/emitter/EventEmitter.js:189:10
in emit
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:425:19
in __callFunction
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:112:6
in __guard$argument_0
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:373:10
in __guard
node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:111:4
in callFunctionReturnFlushedQueue [native code]:null in
callFunctionReturnFlushedQueue
I think is not an Image problem, because I've removed for testing and same error appears.
Usually, you get the Network Error when the REST API server can't be reached. Have you set the correct baseURL or proxy to the Django server? Django server is probably running on 8000 and React is running by default on 3000.
The fact that you see a request on the server-side is a little strange. It will suggest that there might be a bug/problem in the code that is used to process a successful response. Have you tried to remove that code? Yes, might sound strange, just remove the console.log(res, "OK"); and see what will happen?

How can I get the console output in Angular webpage?

I have a Django project which is using Angular as frontend. I have a button which on clicking is scanning the tables in the database. I have some print statements views.py file which is printing the scanned results constantly in the IDE console. I want that output in the webpage. I want that live printing of the console output in the frontend. Can any one know how i can achieve this?
You can achieve this by using server sent events. python can push these console logs to the frontend. Not a expert of python so giving a link below to how to send server side events from python to frontend
https://medium.com/code-zen/python-generator-and-html-server-sent-events-3cdf14140e56
In frontend you can listen to url exposed and as soon as server will push any message on this stream frontend can receive it and push it into component's array and can display over ui.
for frontend code, i am giving a minimal example below :-
import { Injectable, NgZone } from "#angular/core";
import { Observable } from "rxjs";
#Injectable({
providedIn: "root"
})
export class SseService {
constructor(private _zone: NgZone) {}
getServerSentEvent(url: string): Observable<any> {
return Observable.create(observer => {
const eventSource = this.getEventSource(url);
eventSource.onmessage = event => {
this._zone.run(() => {
observer.next(event);
});
};
eventSource.onerror = error => {
this._zone.run(() => {
observer.error(error);
});
};
});
}
private getEventSource(url: string): EventSource {
return new EventSource(url);
}
}
you can susbcribe to getServerSentEvent in above method and can continuously receive new messages, which is in your case your console logs.
You can try calling the following function with the information needed to be displayed.
addItem(val:any) {
let node = document.createElement("li")
let textnode = document.createTextNode(val)
node.appendChild(textnode)
document.getElementById("output").appendChild(node)
}
Make sure to have an element with the id="output".

how to retrieve Python array in javascript (Flask to React communication)

I dumped Python array to a response with json.dumps and now I'm trying to retrieve the data as Javascript list.
#app.route('/get_scales')
#cross_origin()
def get_scales():
classes = inspect.getmembers(sys.modules['mingus.core.scales'], inspect.isclass)
scales = [class_[0] for class_ in classes if ('Error' not in class_[0] and class_[0] != '_Scale')]
return json.dumps(scales)
getScales() {
// create a new XMLHttpRequest
var xhr = new XMLHttpRequest();
// get a callback when the server responds
xhr.addEventListener("load", () => {
// update the state of the component with the result here
console.log(xhr.responseText);
});
// open the request with the verb and the url
xhr.open("GET", "http://127.0.0.1:5000/get_scales");
// send the request
xhr.send();
var formatted_response = JSON.stringify(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
return xhr.responseText;
}
When I made the function in getScales log to console type of xhr.responseText it shows String, but then when trying to parse it with JSON.parse it throws an error. Trying to stringify it first, like above doesn't help either.
I don't know what error it gave, but I think it was actually because xhr.response, wasn't there yet when you tried to use it. This is because XMLrequests function asynchronously, meaning that while the XMLrequest is still waiting for a response, the rest of your code continues executing. Try this instead:
xhr.open('GET', url, false);
the "false" parameter basically says you want your XMLrequest to function synchronously. So the rest of your code will wait for it to finish.
Do keep in mind that your performance may suffer because of this in a lot of situations.
So if you have multiple XMLrequests at a time or Sequentially, you could consider using HTML5 Workers for this.
Or If you don't want your requests to function synchronously (if you can avoid having your XMLrequest function synchronously, you definitely should) you could also try something like this (something like this is defentintely the best option for performance, so if you can use it):
getScales() {
// create a new XMLHttpRequest
var xhr = new XMLHttpRequest();
// get a callback when the server responds
xhr.addEventListener("load", () => {
// update the state of the component with the result here
console.log(xhr.responseText);
var formatted_response = JSON.stringify(xhr.responseText);
console.log(JSON.parse(xhr.responseText));
return xhr.responseText;
});
// open the request with the verb and the url
xhr.open("GET", "http://127.0.0.1:5000/get_scales");
// send the request
xhr.send();
}

NodeJS streaming JSON from python

I'm creating an API with NodeJS. Every request returns a JSON. Some requests call to a python script and I want to send the JSON generated by python to the user. The code would look like:
child = child_process.spawn(cmd, args);
child.stdout.on('data', (chunk) => {
res.write(chunk);
});
child.on('error', function(err) {
res.status(500).json({...});
});
child.on('close', (code) => {
res.end();
});
The problem with this code is that I can't check if the python output is a JSON. Maybe python writes warnings, error...
What can I do to prevent the user will get something different to JSON?.
EDIT
Right now my code is:
var output = [];
command.stdout.on('data', (chunk) => {
output.push(chunk)
});
command.on('close', (code) => {
var stdout = output.join('');
json_cmd = tryParseJSON(stdout)
if (json_cmd)
res.send(json_cmd)...
});
But, I don't want to load all the stdout in a variable. But if I don't do that, I can check if the stdout is a JSON. Can I force python to print just json?. Using always json.dumps and a global try catch would be enough?
Thanks.
Instead of using spawn, you probably want to use exec, which will wait for the Python process to exit and provide you with its output (which you can subsequently try to parse as JSON):
const exec = require('child_process').exec;
...
exec(cmdline, (err, stdout, stderr) => {
if (err) return res.status(500).json({...});
// Try to parse stdout as JSON:
try {
res.json(JSON.parse(stdout));
} catch(e) {
res.status(500).json({...});
}
});
So you need a streaming JSON verifier in NodeJS. The problem is that if you start streaming the json data over the network, and find an error in the JSON halfways, you cannot rollback the traffic to the http headers and change 200 ok to 500 ise. If you want to check the output first you have to accumulate it in the server before sending.
Your current code would do the same. If an error event comes the client will receive a 200 ok with a half stdout and a json object at the end. (Or the response object throws an error if you try to set the status code after it has been sent, I don't know how is this case handled.)

How to make asynchronous HTTP POST requests

I have this program which runs in a loop with pythoncom.PumpMessages().
While this program runs, it takes input and stores it iternally.
When the input reaches a certain lenght, I'd like to send a HTTP POST request asynchronously to a database I have in the cloud so the program doesn't stop taking input while the request is sent. I do not need the request from the server, although it would be nice.
Is this possible? I'm having a hard time figuring this out. Right now it does it synchronously.
Thanks!
This can be done if you use python requests library to send post requests.
It has been answered here.
Asynchronous Requests with Python requests
The example is for "GET" request but you can easily do post request as well.
JavaScript works on any browser without added libraries.
This is great for loading parts of a page without stalling the UI, but use another method (e.g. server or NodeJS) if sending many requests (e.g. >100).
<p id="demo">Customer info will be listed here...</p>
<script>
function showCustomer(str) {
var xmlhttp;
if (str == "") {
document.getElementById("demo").innerHTML = "";
return;
}
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "yourFile.php?queryVariable="+str, true);
xmlhttp.send();
}
</script>
Source: http://www.w3schools.com/xml/tryit.asp?filename=try_dom_xmlhttprequest_database
GET: http://www.w3schools.com/xml/tryit.asp?filename=try_dom_xmlhttprequest_first
More here: http://www.w3schools.com/xml/dom_http.asp

Categories