39 votes

Comment implémenter un serveur minimal pour AJAX en Python?

Je veux créer un très simple HTML/AJAX interface utilisateur graphique basée sur un programme en Python. Si l'interface est une page HTML qui communique avec le programme via AJAX. Pouvez-vous me donner un minimum de mise en œuvre pour le côté serveur à l'aide de l'python SimpleHTTPServer.SimpleHTTPRequestHandler?

Un exemple simple serait un champ de texte et un bouton. Lorsque le bouton est pressé, le contenu du champ est de l'envoyer au serveur qui renvoie alors une réponse correspondante. Je suis conscient qu'il existe de nombreuses solutions performantes pour ce en Python, mais je tiens à garder cette très simple. J'ai déjà trouvé quelques beaux exemples de ce type de serveur (par exemple ici), mais jusqu'à présent, je ne pouvais pas venir avec un vraiment minime.

Dans le cas où vous vous demandez pourquoi je veux implémenter l'interface graphique d'une telle manière: Mon objectif pour cette application est d'afficher beaucoup de données dans une belle mise en page avec un minimum d'interaction - donc, en utilisant du HTML+CSS semble plus pratique (et j'ai déjà été à l'utiliser pour des non-interactif d'affichage de données).

53voto

nikow Points 8887

O. K., je pense que je peux maintenant répondre à ma propre question. Voici un exemple de mise en oeuvre pour calculer le carré d'un nombre sur le serveur. S'il vous plaît laissez-moi savoir si il y a des améliorations ou des idées fausses.

le python de fichiers du serveur:

import threading
import webbrowser
import BaseHTTPServer
import SimpleHTTPServer

FILE = 'frontend.html'
PORT = 8080


class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    """The test example handler."""

    def do_POST(self):
        """Handle a post request by returning the square of the number."""
        length = int(self.headers.getheader('content-length'))        
        data_string = self.rfile.read(length)
        try:
            result = int(data_string) ** 2
        except:
            result = 'error'
        self.wfile.write(result)


def open_browser():
    """Start a browser after waiting for half a second."""
    def _open_browser():
        webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
    thread = threading.Timer(0.5, _open_browser)
    thread.start()

def start_server():
    """Start the server."""
    server_address = ("", PORT)
    server = BaseHTTPServer.HTTPServer(server_address, TestHandler)
    server.serve_forever()

if __name__ == "__main__":
    open_browser()
    start_server()

...et le fichier HTML (je l'appelle "frontend.html' malheureusement, le nom qui doit apparaître dans le code JavaScript en tant que bien):

<html>
<head>
<title>AJAX test</title>
</head>
<body>
<script type="text/javascript">

function xml_http_post(url, data, callback) {
    var req = false;
    try {
        // Firefox, Opera 8.0+, Safari
        req = new XMLHttpRequest();
    }
    catch (e) {
        // Internet Explorer
        try {
            req = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            try {
                req = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e) {
                alert("Your browser does not support AJAX!");
                return false;
            }
        }
    }
    req.open("POST", url, true);
    req.onreadystatechange = function() {
        if (req.readyState == 4) {
            callback(req);
        }
    }
    req.send(data);
}

function test_button() {
    var data = document.test_form.test_text.value;           
    xml_http_post("frontend.html", data, test_handle)
}

function test_handle(req) {
    var elem = document.getElementById('test_result')
    elem.innerHTML =  req.responseText
}

</script>

<form name=test_form>
sqr(
<input type="text" name="test_text" value="0" size="4">
) =
<span id="test_result">0</span>
<input type=button onClick="test_button();" value="start" title="start">
</form>

</body>
</html>

Bien sûr, il serait beaucoup plus pratique à utiliser jQuery pour la requête XML, mais dans l'intérêt de simplicité, je vais le laisser comme ça.

Enfin une alternative de mise en œuvre à l'aide de WSGI (malheureusement je n'ai pas vu un moyen de retomber sur le fichier standard-servir le gestionnaire si la demande n'est pas un POST):

import threading
import webbrowser
from wsgiref.simple_server import make_server

FILE = 'frontend.html'
PORT = 8080

def test_app(environ, start_response):
    if environ['REQUEST_METHOD'] == 'POST':
        try:
            request_body_size = int(environ['CONTENT_LENGTH'])
            request_body = environ['wsgi.input'].read(request_body_size)
        except (TypeError, ValueError):
            request_body = "0"
        try:
            response_body = str(int(request_body) ** 2)
        except:
            response_body = "error"
        status = '200 OK'
        headers = [('Content-type', 'text/plain')]
        start_response(status, headers)
        return [response_body]
    else:
        response_body = open(FILE).read()
        status = '200 OK'
        headers = [('Content-type', 'text/html'),
                   ('Content-Length', str(len(response_body)))]
        start_response(status, headers)
        return [response_body]

def open_browser():
    """Start a browser after waiting for half a second."""
    def _open_browser():
        webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
    thread = threading.Timer(0.5, _open_browser)
    thread.start()

def start_server():
    """Start the server."""
    httpd = make_server("", PORT, test_app)
    httpd.serve_forever()

if __name__ == "__main__":
    open_browser()
    start_server()

11voto

S.Lott Points 207588

Utilisez l' implémentation de référence WSGI . À long terme, vous serez plus heureux.

 from wsgiref.simple_server import make_server, demo_app

httpd = make_server('', 8000, demo_app)
print "Serving HTTP on port 8000..."

# Respond to requests until process is killed
httpd.serve_forever()
 

Demo_app est relativement facile à écrire; il gère vos demandes Ajax.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X