How to connect Javascript to Python sharing data with JSON format in both ways?

36,374

Solution 1

I found finally an easier way than Flask. It's a Python framework called Bottle You only need to download the library from the official web site and put all its files in your working directory in order to import the library. You can also install it using the setup python program included to avoid carrying with the sourcecode everywhere. Then, for making your Web Service Server you can code it like this:

from bottle import hook, response, route, run, static_file, request
import json
import socket
import sqlite3

#These lines are needed for avoiding the "Access-Control-Allow-Origin" errors
@hook('after_request')
def enable_cors():
    response.headers['Access-Control-Allow-Origin'] = '*'

#Note that the text on the route decorator is the name of the resource
# and the name of the function which answers the request could have any name
@route('/examplePage')
def exPage():
    return "<h1>This is an example of web page</h1><hr/><h2>Hope you enjoy it!</h2>"

#If you want to return a JSON you can use a common dict of Python, 
# the conversion to JSON is automatically done by the framework
@route('/sampleJSON', method='GET')
def mySample():
    return { "first": "This is the first", "second": "the second one here", "third": "and finally the third one!" }

#If you have to send parameters, the right sintax is as calling the resoure
# with a kind of path, with the parameters separed with slash ( / ) and they 
# MUST to be written inside the lesser/greater than signs  ( <parameter_name> ) 
@route('/dataQuery/<name>/<age>')
def myQuery(name,age):
    connection= sqlite3.connect("C:/folder/data.db")
    mycursor = connection.cursor()
    mycursor.execute("select * from client where name = ? and age= ?",(name, age))
    results = mycursor.fetchall()
    theQuery = []
    for tuple in results:
        theQuery.append({"name":tuple[0],"age":tuple[1]})
    return json.dumps(theQuery)

#If you want to send images in jpg format you can use this below
@route('/images/<filename:re:.*\.jpg>')
def send_image(filename):
    return static_file(filename, root="C:/folder/images", mimetype="image/jpg")

#To send a favicon to a webpage use this below
@route('/favicon.ico')
def favicon():
    return static_file('windowIcon.ico', root="C:/folder/images", mimetype="image/ico")

#And the MOST important line to set this program as a web service provider is this
run(host=socket.gethostname(), port=8000)

Finally, you can call the REST web service of your Bottlepy app on a Javascript client in this way:

var addr = "192.168.1.100"
var port = "8000"

function makeQuery(name, age){
    jQuery.get("http://"+addr+":"+port+"/dataQuery/"+ name+ "/" + age, function(result){
        myRes = jQuery.parseJSON(result);
        toStore= "<table border='2' bordercolor='#397056'><tr><td><strong>name</strong></td><td><strong>age</strong></td></tr>";
        $.each(myRes, function(i, element){
            toStore= toStore+ "<tr><td>"+element.name+"</td><td>" + element.age+ "</td></td></tr>";
        })
        toStore= toStore+ "</table>"
        $('#theDataDiv').text('');
        $('<br/>').appendTo('#theDataDiv');
        $(toStore).appendTo('#theDataDiv');
        $('<br/>').appendTo('#theDataDiv');
    })
}

I hope it could be useful for somebody else

Solution 2

Here's a "hello world" example of a flask web-application that can serve static html and javascript files, search database using parameter from a javascript request, and return results to javascript as json:

import sqlite3
from flask import Flask, jsonify, g, redirect, request, url_for

app = Flask(__name__)

@app.before_request
def before_request():
    g.db = sqlite3.connect('database.db')

@app.teardown_request
def teardown_request(exception):
    if hasattr(g, 'db'):
        g.db.close()

@app.route('/')
def index():
    return redirect(url_for('static', filename='page.html'))

@app.route('/json-data/')
def json_data():
    # get number of items from the javascript request
    nitems = request.args.get('nitems', 2)
    # query database
    cursor = g.db.execute('select * from items limit ?', (nitems,))
    # return json
    return jsonify(dict(('item%d' % i, item)
                        for i, item in enumerate(cursor.fetchall(), start=1)))

if __name__ == '__main__':
    app.run(debug=True, host='localhost', port=5001) # http://localhost:5001/
else:
    application = app # for a WSGI server e.g.,
    # twistd -n web --wsgi=hello_world.application --port tcp:5001:interface=localhost

The database setup code is from Using SQLite 3 with Flask.

static/page.html and static/json-jquery.js files are from Ajax/jQuery.getJSON Simple Example, where the javascript code is modified slightly to pass a different url and nitems parameter:

$(document).ready(function(){
    $('#getdata-button').live('click', function(){
        $.getJSON('/json-data', {'nitems': 3}, function(data) {
            $('#showdata').html("<p>item1="+data.item1+" item2="+data.item2+" item3="+data.item3+"</p>");
        });
    });
});

Solution 3

Your question amounts to "how do I make this python into a webservice".

Probably the most lightweight ways to do that are web.py and flask. Check them out.

If this is getting bigger, consider django with tastypie - that's a simple way to make a json-based api.

Update: Apparently, there is also a python-javascript RPC framework called Pico, to which Felix Kling is a contributor. The intro says:

Literally add one line of code (import pico) to your Python module to turn it into a web service that is accessible through the Javascript (and Python) Pico client libararies.

Share:
36,374
AngelBlond8
Author by

AngelBlond8

Visual Basic 6, Java and C Programmer, Student of Computing Engineering on Universidad Simón Bolivar in Caracas, Venezuela

Updated on August 17, 2020

Comments

  • AngelBlond8
    AngelBlond8 almost 4 years

    I'm trying to find out how to create a local connection between a Python server and a Javascript client using the JSON format for the data to be retrieved. Particularly, I need to make some queries on the HTML client side, send these queries to the server on JSON format and run them on the Python server side to search for data on a SQLite Database. And after getting the results from the database, send those results back to the client in JSON format too.

    By now, I just can run the query on Python and code it on JSON like this:

    import sqlite3 as dbapi
    import json
    
    connection = dbapi.connect("C:/folder/database.db")
    mycursor = connection.cursor()
    mycursor.execute("select * from people")
    results = []
    for information in mycursor.fetchall():
            results += information
    
    onFormat = json.dumps(results)
    print(onFormat)
    

    I know this code does something alike (in fact it runs), because it calls a service on a server which returns data in JSON format (but the server in this example is NOT Python):

    <html>
        <head>
            <style>img{ height: 100px; float: left; }</style>
            <script src="http://code.jquery.com/jquery-latest.js"></script>
        </head>
        <body>
            <div id="images"></div>
        <script>
          $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?",
          {
            tags: "mount rainier",
            tagmode: "any",
            format: "json"
          },
          function(data) {
            $.each(data.items, function(i,item){
              $("<img/>").attr("src", item.media.m).appendTo("#images");
              if ( i == 3 ) return false;
            });
          });</script>
    
        </body>
    </html>
    

    What I need is to know how should I run (locally) the python program to be an available running web-service and how should be the Javascript to retrieve the data from the python server.

    I've looking for this on internet everywhere but I didn't find this answer anywhere because the only answers they give are on how to code JSON inside Python or inside Javascript but not connecting both. Hope somebody can help me on this!!!

  • Florin Stingaciu
    Florin Stingaciu over 11 years
    Sorry to bring up old threads. I just have a question. Aren't there security implications with just taking the arguments and feeding them directly in the database? I'm not being critical; just curios. I'm trying to understand how JSON works. Can't anyone call upon this API therefore making it liable to sql injection attacks?
  • jfs
    jfs over 11 years
    @FlorinStingaciu: It is a parameterized query. The engine escapes all arguments.
  • Marcin
    Marcin about 10 years
    And what makes bottle easier than flask?