How to communicate between JavaScript and Python in a CGI script - javascript

I have a CGI script which runs on local host. It has a Python function named compute(argument 1) and prints html tags along with a JavaScript function called onClick which gets called when a button is clicked on the browser. I am not sure how to communicate between JavaScript and Python here.
Here is a snippet of the CGI file
import cgi
def worker():
#Does something here and returns an python list called data
def compute(index)
#Does something with data[index] and returns another python list called data2
print ("Content-type: text/html")
print ()
print ("<html>")
print ("<head>")
print ("<title>Worker</title>")
print("""<script type = "text/javascript">
var count = 0;
function onClick(){
count = count+1;
document.getElementById("dis").innerHTML = count;
};
</script>""")
print ("</head>")
print ("<body>")
<button type = "button" class = "next" onclick = "onClick()" >Next → </button>
print("""Count: <p id = "dis" > 0 </p>""")
print ("</body>")
print ("</html>")
My question here is how do I make the JavaScript function OnClick() call the python function compute() by passing variable count as a parameter and then storing the resulting list returned by compute() as a JavaScript variable. It would be better if worker function does not have to be called again. It would be fine to even return a single variable in compute(index) rather than a python list and pass it to JavaScript. Thanks in advance :).

AJAX/JQUERY can send the data, JSON for instance, to your python endpoint. But your script is not a server. You need a server a.k.a middleware like apache. POST via AJAX to your server adress:
$(function(){
$.ajax({
url: "ServerAdress/cgi-bin/" + service.py,
type: "POST",
async:true,
data: {key_vehicule: 'mercedes'},
success: function(response){
},
error: function(){
},
complete: function(){
}
});
Be sure to have your server configured to execute the python script with the python interpeter and all the right it needs. In the python script, just importing the cgi is not enought, you need the to receive the data:
form = cgi.FieldStorage()
vehicule = form.getvalue('key_vehicule')

Related

Keeping a backend function open in javascript

So I have a pretty simple python function sitting in the backend as follows:
def iterator():
for i in range(1000):
random_var = randrange(1000)
return jsonify({
"random_var" : random_var,
})
time.sleep(4)
When I run this function standalone, it runs for well a 1000 times very slowly generating a random number every 4 seconds. What I want is to connect this to html frontend via javascript and the code for that is as follows:
var Output_value = document.getElementById('Output_value');
$(function() {
$('#exe-btn').click(function(){
$.ajax({
url: '/display/',
success: function(data) {Output_value.innerHTML = data['random_var'];} });
}
);
});
This does work but not exactly as I expect it to.
Frontend
It displays the value once and then just stops and doesn't display it again unless I press the button again.
What I've researched so far:
The two potential candidates that I found to solve this included the setInterval and setTimeout functions in jquery, however the flaw with that approach is that they require the execution of the backend python function again and again, while what I require is that function to be executed only once.
What I want it to do
I want the backend iterator() to be executed only once and then the values of it to be returned to js so that the newest value is displayed on the html frontend and taking the place of the previous value.
What is happening right now is that the function in the backend is executed upon click but it stops streaming the output after returning one result.
The only way to do this is using websockets as Sergey said. The architecture for that is pretty simple though.
Keep an id in the html which will be used by the javascript to output the data it receives from the flask server. The flask server will use socket io and the javascript file will also use socket. The way it will work is that once the execute button on the frontend is pressed, the js calls an event in the backend which will receive it and then transmit out the data that you want to transmit. This is what the html code looks like:
<div class="Output">
<table>
<th ><h2>Python Library Output:</h2></th>
<th id="Output_value"> </th>
</table>
</div>
<div class= "execute_button">
<button id="exe-btn">Execute</button>
</div>
The exe-btn here is what we bind to jquery, which will call the module execution event in the backend. The JS code:
//Creating the event for execution of backend iterator script
//Setting up the event to be executed when the execute button is clicked and not otherwise
$(function() {
$('#exe-btn').click(function(){
socket.emit('module_trigger', {
data: 'Module event triggered'
})
}
);
});
socket.on( 'module_trigger_stream', function( msg ) {
console.log( 'Response 2')
console.log(msg['add'])
Output_value.innerHTML = msg['add']
//console.log(msg['message'])
}
);
Now the final step is to set up the handlers in the backend and also the method for creating the data. I use a simple random number generator which keeps emitting values after some time:
from flask import Flask, jsonify, render_template
from flask_socketio import SocketIO, send
import math
import time
#module imports
from random import randrange
import json
app = Flask(__name__,template_folder ='templates/')
app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
socketio = SocketIO(app)
#socketio.on('module_trigger')
def handle_module_trigger(jsons, methods=['GET','POST']):
print('Trigger successfully executed')
print(str(jsons))
for i in range(1000):
random_var = randrange(1000)
time.sleep(4)
print("The random variable is " + str(random_var))
out = {'add' : str(random_var)}
socketio.emit('module_trigger_stream',out)
#app.route("/",methods=['GET','POST'])
def render_output():
return render_template("index.html" )
if __name__ == "__main__":
socketio.run(app,debug=True)

Ajax not getting most recent version of JSON file

I'm rather new to terminology and coding in general, but I've tried to trim down my code, though it may still have redundancies. Thanks in advance for your understanding.
I'm using an ajax and php script to write some data to a file on the server called data.json. The script works fine, and opening the json file shows that it's indeed updated with the data. The json file simply contains an array of objects.
Here's the code that does this:
function writeData() {
$.ajax({
type : "POST",
url : "save.php",
async : true,
data : {
json : JSON.stringify(dataToWrite)
}
});
document.getElementById('success-box').innerHTML = "Data successfully written.";
};
...and the PHP:
<?php
$json = $_POST['json'];
$file = fopen('data.json','w+');
fwrite($file, $json);
fclose($file);
?>
The problem I'm having is this: The user can navigate to a separate HTML page, and can click a button to view the data in the json file in a nicely-formated way. This is done via another ajax script that reads the data. This latter ajax script doesn't seem to be able to "see" the newly updated json file. It instead loads the old version of the file, before it was updated with the first ajax script. I'm sure that this second ajax script is run after the above writeData() is finished, because it's actually on a separate HTML page entirely, which is loaded later, after the user clicks a button.
Here's the second ajax script that reads the data from the data.json file (it's on another, separate HTML page):
$.ajax({
type : "GET",
url : "http://eslquiz.net/ell_errors/data.json",
async : true,
dataType : 'json',
success : function(response) {
data = response;
document.getElementById('main').innerHTML = `
<div id='top-stuff'>
<button onClick='viewData()'>Reset Filter</button>
<button onclick="print2()">Print Worksheet</button>
</div>
<br>
<div id='left-column' class='column'></div>
<div id='right-column' class='column'></div>
`;
leftColumn = document.getElementById('left-column');
rightColumn = document.getElementById('right-column');
leftColumn.innerHTML = "<b>Sentences:</b> <br><br>";
rightColumn.innerHTML = "<b>Errors:</b> <br><br>";
//add the sentences and their errorTypes:
for (i=0; i<data.length; i++) {
var senBox = document.createElement('div');
senBox.className = 'box';
senBox.setAttribute('id', 'sen' + i)
senBox.innerHTML += data[i].text;
var errBox = document.createElement('div');
errBox.className = 'box';
errBox.setAttribute('id', 'err' + i)
errBox.innerHTML += data[i].errorType;
leftColumn.appendChild(senBox);
rightColumn.appendChild(errBox);
}
}
});
All of these files are hosted in the same directory on One.com.
The strange thing is that when I manually open the data.json file and edit its contents in any way (by deleting everything, for example), the next time the ajax call is made, it reads the version I just manually updated. This makes me think it might be something to do with the One.com server refreshing itself?
I tried adjusting the ajax between synchronous/asynchronous, and using cache: false, but these don't seem to affect anything.
I've searched around, and can't seem to find out what's going on here. Thanks for any guidance you could provide.
Thanks. I ended up using the following:
jQuery.ajaxSetup({
cache: false
});
I tried using this before, but for some reason it didn't work, not sure why. But it's working now! Thanks.
first, GET method can be cached by the browser.
second, Make sure the response is a json type
$.ajax({
type : "GET",
url : "http://eslquiz.net/ell_errors/data.json?rand_v=" + Matn.random(), // add a random try again
async : true,
dataType : 'json',
success : function(response) {
// Make sure the response is a json type
// console.log(typeof(response));
// console.log(typeof(JSON.parse(response)));
data = response;
// ...

Javascript scope of array and converting js array to a php array

Edit/Clarification: I have a php page, call it displayPhotos.php, in which I set up an Ajax call to a different php page, call it getPhotos.php, which queries a database and returns photo information (caption, file name etc) to displayPhotos.php where they are displayed. I use php in displayPhotos to manipulate the data returned from getPhotos. The returned data from the Ajax call is a javascript 2-dimensional array. I need to turn the javascript array into a php array so I can do they display and other stuff. How do I do that?
Hope this helps.
My eyes hurt from reading all of the docs.
I want to use ajax to query a database, return the data then use php to continue with the web page.
All of the examples I've looked at start with creating the json in php. I need to start with the json object in javascript.
<script>
var photoarray = [];
var ajaxRequest = $.ajax
({
url : "fhs_get_photos.php",
type: "POST",
dataType: "json",
success: function(photo_array)
{
photoarray = photo_array;
//line below works. the file name is correct but disappears
//outside of this function
console.log("photoarray[0][file_name] is: " + photoarray[0]['file_name']);
},
error: function(request, status, error)
{
alert('An error occurred: ' );
}
});
In this instance I'm not passing anything to the php file that query's the db. The console log shows that the file name in photoarray is correct but once outside of this function it disappears even though it's declared as global, I think it is anyway. Why and what do I need to do to fix this.
The php file just does a SELECT * FROM..... and returns everything.
// in fhs_get_photos.php
// SELECT * FROM table......
echo $json = json_encode($result);
return $json;
So I now have the array back but it's in javascript. Once I figure out the scope problem, how can I convert this javascript array to a php array?
<h3>Welcome to the Historical Society's historical photo archive
</h3>
</header>
<figure id="photo_figure">
<script>
//line below gets me: SCRIPT5007: Unable to get property 'thumb' of
//undefined or null reference
console.log("photoarray thumb: ") + photoarray[0]['thumb'];
</script>
Am I explaining this properly?
First of all AJAX is async. This means it sends the request when you ask it to, but receives the response sometime later in the future. And it works after php has rendered and sent the page. So. When you get an update via AJAX, you have to use javascript to make that update matter. The most simple solution is to process the response right there in the success callback. That way you don't need to mess with the global scope (which is a bad practice).
Supposedly, your HTML is like this:
<header>
<h3>Welcome to the Historical Society's historical photo archive
</h3>
</header>
<div id="figures"></div>
You can do it by declaring a function that handles the processing:
function updateDom(photoArr) {
var $figures = $('#figures');
$.each(photoArr, function() {
console.log(this);
$figures.append('<img src="' + this.thumb +'">');
});
}
Code below is placed in the success callback
And execute that function in the success callback and pass it the array from json, that was parsed and became a valid js object.
var photoArray = JSON.parse(photo_array);
updateDom(photoArray);
here's the fiddle, but it's for the DOM part only

Return result to a PHP variable from AJAX in a jQuery function

So this is the hardest thing I've ever tried to do, I cannot find any answers after 1 day of searching. Note that I am using some custom jQuery API and will explain what it does.
The setup is a php page that contains a jQuery function. That jQuery function calls the API to return a result based on a row I clicked (it is jQgrid, basically looks like an online excel sheet). That works fine, but the objective is to get that result OUT of the jQuery function and store it in a PHP variable. I am just clueless......
Main PHP Page:
$getUnitID = <<<getUnitID //This is the jQuery function. It is stored in a php variable for use in other functions of the API
function(rowid, selected)
{
var selr= null;
if(rowid != null){
selr = jQuery('#grid').jqGrid('getGridParam','selrow'); //This will give ma a number result based on the row I selected. Works fine.
$.ajax({ // I believe I need to use AJAX so here is my attempt
type: "POST",
url: "getId.php", //This is another PHP page for the reuslt. See below
dataType: "json",
data: {selr:selr},
success: function(data) {
alert (data); // This will successfully show me the row number I chose as an alert. But I don't want an alert, I want it stored as a php variable in my main document to use elsewhere.
}
});
}
}
getUnitID; //End of the function
$grid->setGridEvent('onSelectRow',$getUnitID); //Just an event that calls the function upon clicking the row
$rowResult = ??????? //I need this variable to store the result of that AJAX call or that function call
getId.php
<?php
$rId = $_POST["selr"];
echo $rId;
?>
Essentially, I have no idea why I am using AJAX, because my result is still stuck inside the main jQuery function. How in God's name do I get it OUTSIDE that function?!?!?!?!?!?!?! Do I need to $_GET the 'selr' that I POSTed to getId.php ? If so, how?
Thank you, I love you all.
By the time you get that AJAX request sent out and response received, PHP has already gone to sleep. You cant give the data back to your same page's PHP code. Your jQuery starts executing on client computer long after PHP has already finished its work on your server.
It doesn't matter whether your JavaScript function is stored in a PHP variable. PHP will not get its output back. Only way you can do so is to launch another new request to that code and send value to it. but on the same very request on the same very page, its a no no.
Example of how you can send that data to another PHP page
//Your existing jQuery
success: function(data) {
// alert (data);
var result=data;
$.ajax({
type: "POST",
url: "anotherpage.php",
data: { data: result }
});
}

How can I use jQuery to run MySQL queries?

Is it possible to run a MySQL query using jQuery? I'm trying to emulate the functionality of voting on SE sites.
The vote counter on SE automatically updates without the need to reload the page (which is what I currently have, a hidden form that re-submits to the current page but runs a small block on PHP that updates the score of a question in the database). I'm assuming that is being done using Javascript/jQuery seeing as it is dynamic.
How can I do this? Is there a library which makes it easy and simple (like PHP)?
You can use ajax to call a server page (PHP / ASP /ASP.NET/JSP ) and in that server page you can execute a query.
http://api.jquery.com/jQuery.ajax/
HTML
<input type='button' id='btnVote' value='Vote' />
Javascript
This code will be excuted when user clicks on the button with the id "btnVote". The below script is making use of the "ajax" function written in the jquery library.It will send a request to the page mentioned as the value of "url" property (ajaxserverpage.aspx). In this example, i am sending a querystring value 5 for the key called "answer".
$("#btnVote").click(function(){
$.ajax({
url: "ajaxserverpage.aspx?answer=5",
success: function(data){
alert(data)
}
});
});
and in your aspx page, you can read the querystring (in this example, answer=5) and
build a query and execute it againist a database. You can return data back by writing a Response.Write (in asp & asp.net )/ echo in PHP. Whatever you are returning will be coming back to the variable data. If your query execution was successful, you may return a message like "Vote captured" or whatever appropriate for your application. If there was an error caught in your try-catch block, Return a message for that.
Make sure you properly sanitize the input before building your query. I usually group my functionalities and put those into a single file. Ex : MY Ajax page which handles user related stuff will have methods for ValidateUser, RegisterUser etc...
EDIT : As per your comment,
jQuery support post also. Here is the format
$.post(url, function(data) {
alert("Do whatever you want if the call completed successfully")
);
which is equivalent to
$.ajax({
type: 'POST',
url: url,
success: function(data)
{
alert("Do whatever you want if the call completed successfully")
}
});
This should be a good reading : http://en.wikipedia.org/wiki/Same_origin_policy
It's just a few lines in your favorite language.
Javascript
$.post('script.php', { id: 12345 }, function(data) {
// Increment vote count, etc
});
PHP (simplified)
$id = intval($_POST['id']);
mysql_query("UPDATE votes SET num = num + 1 WHERE id = $id");
There are many different ways to accomplish this.

Categories