How to Implement a Minimal Server for Ajax in Python

How to implement a minimal server for AJAX in Python?

O.K., I think I can now answer my own question. Here is an example implementation for calculating the square of a number on the server. Please let me know if there are any improvements or misconceptions.

the python server file:

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()

...and the HTML file (I call it 'frontend.html', unfortunately the name has to appear in the JavaScript code as well):

<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>

Of course it would be much more convenient to use jQuery for the XML request, but in the interest of simplicity I'll leave it like that.

Finally an alternative implementation using WSGI (unfortunately I didn't see a way to fall back on the standard file-serving handler if the request is not a 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()

How do I integrate Ajax with Django applications?

Even though this isn't entirely in the SO spirit, I love this question, because I had the same trouble when I started, so I'll give you a quick guide. Obviously you don't understand the principles behind them (don't take it as an offense, but if you did you wouldn't be asking).

Django is server-side. It means, say a client goes to a URL, you have a function inside views that renders what he sees and returns a response in HTML. Let's break it up into examples:

views.py:

def hello(request):
return HttpResponse('Hello World!')

def home(request):
return render_to_response('index.html', {'variable': 'world'})

index.html:

<h1>Hello {{ variable }}, welcome to my awesome site</h1>

urls.py:

url(r'^hello/', 'myapp.views.hello'),
url(r'^home/', 'myapp.views.home'),

That's an example of the simplest of usages. Going to 127.0.0.1:8000/hello means a request to the hello() function, going to 127.0.0.1:8000/home will return the index.html and replace all the variables as asked (you probably know all this by now).

Now let's talk about AJAX. AJAX calls are client-side code that does asynchronous requests. That sounds complicated, but it simply means it does a request for you in the background and then handles the response. So when you do an AJAX call for some URL, you get the same data you would get as a user going to that place.

For example, an AJAX call to 127.0.0.1:8000/hello will return the same thing it would as if you visited it. Only this time, you have it inside a JavaScript function and you can deal with it however you'd like. Let's look at a simple use case:

$.ajax({
url: '127.0.0.1:8000/hello',
type: 'get', // This is the default though, you don't actually need to always mention it
success: function(data) {
alert(data);
},
failure: function(data) {
alert('Got an error dude');
}
});

The general process is this:

  1. The call goes to the URL 127.0.0.1:8000/hello as if you opened a new tab and did it yourself.
  2. If it succeeds (status code 200), do the function for success, which will alert the data received.
  3. If fails, do a different function.

Now what would happen here? You would get an alert with 'hello world' in it. What happens if you do an AJAX call to home? Same thing, you'll get an alert stating <h1>Hello world, welcome to my awesome site</h1>.

In other words - there's nothing new about AJAX calls. They are just a way for you to let the user get data and information without leaving the page, and it makes for a smooth and very neat design of your website. A few guidelines you should take note of:

  1. Learn jQuery. I cannot stress this enough. You're gonna have to understand it a little to know how to handle the data you receive. You'll also need to understand some basic JavaScript syntax (not far from python, you'll get used to it). I strongly recommend Envato's video tutorials for jQuery, they are great and will put you on the right path.
  2. When to use JSON?. You're going to see a lot of examples where the data sent by the Django views is in JSON. I didn't go into detail on that, because it isn't important how to do it (there are plenty of explanations abound) and a lot more important when. And the answer to that is - JSON data is serialized data. That is, data you can manipulate. Like I mentioned, an AJAX call will fetch the response as if the user did it himself. Now say you don't want to mess with all the html, and instead want to send data (a list of objects perhaps). JSON is good for this, because it sends it as an object (JSON data looks like a python dictionary), and then you can iterate over it or do something else that removes the need to sift through useless html.
  3. Add it last. When you build a web app and want to implement AJAX - do yourself a favor. First, build the entire app completely devoid of any AJAX. See that everything is working. Then, and only then, start writing the AJAX calls. That's a good process that helps you learn a lot as well.
  4. Use chrome's developer tools. Since AJAX calls are done in the background it's sometimes very hard to debug them. You should use the chrome developer tools (or similar tools such as firebug) and console.log things to debug. I won't explain in detail, just google around and find out about it. It would be very helpful to you.
  5. CSRF awareness. Finally, remember that post requests in Django require the csrf_token. With AJAX calls, a lot of times you'd like to send data without refreshing the page. You'll probably face some trouble before you'd finally remember that - wait, you forgot to send the csrf_token. This is a known beginner roadblock in AJAX-Django integration, but after you learn how to make it play nice, it's easy as pie.

That's everything that comes to my head. It's a vast subject, but yeah, there's probably not enough examples out there. Just work your way there, slowly, you'll get it eventually.

WSGI Web frontend (using jquery, AJAX, css) for python backend

WSGI is an interface between the webserver (like Apache) and your Python web application. It provides a standard way of running Python code on web servers.

You do not need WSGI to serve static files like JavaScript or CSS (because JS/CSS is not a Python code). Configure your web server to serve static files in a normal way, apart of your WSGI-based Python web application.

With Apache typical solution is to use Alias directive:

Alias /media/ /usr/local/www/documents/media/              # Static files, e.g. http://example.com/media
WSGIScriptAlias / /usr/local/www/wsgi-scripts/myapp.wsgi # WSGI app mounted at the root of site, e.g. http://example.com

Minimal Example for dynamic HTML pages with Django and AJAX

Your HTML is not valid, for a couple of reasons.

First, you put the script block outside the closing </html> tag. That means it's outside the document itself, and may not be read by the browser.

More importantly, you haven't got your code inside a proper script element. You have an opening tag, but you use that to reference the external jQuery library via the src attribute. You don't have a closing tag at all

You need to put the jQuery reference in its own element, and use proper opening and closing tags for your own script.

<html>
<body>
<table>
...
</table>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
var append_increment = 0;
setInterval(function() {
$.ajax({
type: "GET",
url: "{% url 'get_more_tables' %}",
data: {'append_increment': append_increment}
})
.done(function(response) {
$('#_appendHere').append(response);
append_increment += 10;
});
}, 1000)
</script>
</body>
</html>

Having Trouble Getting SimpleHTTPRequestHandler to respond to AJAX

Make sure your response has a send_header() with a content type. I have seen AJAX requests get confused without this. You can also try switching your POST to a GET for debugging and make sure the browser can see the content.

Here is a simple HTTP example for returning XML if you point your query or browser to 127.0.0.1/test:

import SimpleHTTPServer, SocketServer
import urlparse

PORT = 80

class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):

# Parse query data & params to find out what was passed
parsedParams = urlparse.urlparse(self.path)
queryParsed = urlparse.parse_qs(parsedParams.query)

# request is either for a file to be served up or our test
if parsedParams.path == "/test":
self.processMyRequest(queryParsed)
else:
# Default to serve up a local file
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self);

def processMyRequest(self, query):

self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.end_headers()

self.wfile.write("<?xml version='1.0'?>");
self.wfile.write("<sample>Some XML</sample>");
self.wfile.close();

Handler = MyHandler

httpd = SocketServer.TCPServer(("", PORT), Handler)

print "serving at port", PORT
httpd.serve_forever()


Related Topics



Leave a reply



Submit