Archive for February, 2010|Monthly archive page

Python and AJAX tutorial for beginners with web.py and jQuery

Note: I’m always surprised to see this at the top of a Google search for ‘ajax python’. It has been three and a half years after all (though I guess that’s how these things work sometimes). I haven’t been following the state of Python web development at all, so this code may be badly out-of-date, simply not work, etcetera. If you’re just starting out on your Pythonic path, I feel like my best recommendation is to Google on, my friend, Google on…

– George
14 September, 2013

As a result of following along with the NYU class Reading and Writing Electronic Text I started to get into using Python for web apps — this, along with learning JavaScript, is something I’d been wanting to do for a while.

I’ll try to summarize what I’ve learned over the last week or so. What I was looking for was a simple way to get into this stuff, and as I discovered it’s not so simple, for a hobbyist like myself, once you combine two or three frameworks in a project. Maybe this post will help someone else in the same situation.

Python already was the choice for the server-side script. What I then needed was a way for the browser to communicate with the script. There are literally dozens of ways to do this, and the Python wiki has a good page on web programming. I also found this conversation springing from a post by the BDFL at Artima a good read, though it’s a few years old now.

I decided to keep it simple (though I still want to learn frameworks like Django, TurboGears, etcetera at some point in the future). I considered looking into using CGI with Python, but then I found web.py, a lightweight web framework, and liked it immediately.

The web.py framework can run its own basic web server or interface with others such as Apache or lighttpd. It includes a simple HTML template language that basically is just HTML + Python. It works with databases or not. In short it has all you need to get things running quickly.

So I had the server language and the web framework. All that remained was the client-side. Rather than rolling all the JavaScript myself I went with the jQuery library. I had heard some good things and it looked good when I checked it out.

OK, first let’s look at the basic project structure. Note that I’m using web.py’s templates, though this isn’t required:

- webpy_jquery_ajax_tutorial
  - static
      jquery.js
     tutorial.css

  - templates
    tutorial.html
  app.py

Within the project directory we include the static and templates directories (required terms for web.py). Files such as CSS, JavaScript, images, and so on are put in static. HTML templates go in templates, and everything else can go in the main project directory.

Our app.py is the web.py script that controls our app. It looks like this:

import web

def make_text(string):
    return string

urls = ('/', 'tutorial')
render = web.template.render('templates/')

app = web.application(urls, globals())

my_form = web.form.Form(
                web.form.Textbox('', class_='textfield', id='textfield'),
                )

class tutorial:
    def GET(self):
        form = my_form()
        return render.tutorial(form, "Your text goes here.")
        
    def POST(self):
        form = my_form()
        form.validates()
        s = form.value['textfield']
        return make_text(s)

if __name__ == '__main__':
    app.run()

Other than the simple echo function defined for this tutorial, there are some critical parts to the code above, so let's look at it more closely.

First of all web.py will map the URL to classes in the script. That's why we have urls = ('/', 'tutorial'), which says map the root URL address to what happens in the tutorial class defined later.

Second, if we're using templates we tell web.py where to find our HTML templates with render = web.template.render('templates/'). The my_form creates an HTML text entry box that we'll render later. We give it an empty string for a name simply for aesthetic reasons (otherwise you'll see it on the HTML page).

Finally we define the tutorial class. We create the GET and POST methods ( web.py intentionally requires this)to define the behaviour of our web.py app in response to browser client requests. Looking at GET:

    def GET(self):
        form = my_form()
        return render.tutorial(form, "Your text goes here.")

Defining form = my_form() gives us a copy of the form instance we created earlier. The method render.tutorial() returns a rendering of the tutorial HTML template (using the same name tutorial here in the class definition, the call, and eventually the HTML template are important here!), passing the arguments form and the text string to the template at the same time.

Now for POST:

    def POST(self):
        form = my_form()
        form.validates()
        s = form.value['textfield']
        return make_text(s)

Again using a copy of the form instance, we automatically validate it (simply because I haven't learned how to validate forms yet!). We can then access the value of our textfield box with form.value['textfield'], and send it to our echo function defined earlier.

That's all you need in the app.py, now to look at the HTML template (located in the templates directory):

$def with (form, text)

<!doctype html>

<html>

    <head>
        <title>Hello</title>
        <link rel="stylesheet" type="text/css" href="/static/tutorial.css" />
        
        <script type="text/javascript" src="/static/jquery.js"></script>
        
        <script type="text/javascript">
                                jQuery(document).ready(function() {
                                jQuery(".button").click(function() {
                                        var input_string = $$("input#textfield").val();
                                        jQuery.ajax({
                                                type: "POST",
                                                data: {textfield : input_string},
                                                success: function(data) {
                                                jQuery('#foo').html(data).hide().fadeIn(1500);
                                                },
                                                });
                                        return false;
                                        });
                                });
        
                        </script>
    </head>
    
    <body>
        <br>
        <form class="form" method="post"> 
        $:form.render()
        <input class="button" type="submit" value="send"/>    
        </form>

        <br><br>
        <span id="foo">$text</span>        
    </body>
    
</html>

(we'll see how WP handles the syntax styling with that...)

There's a little more going on here so let's take it one step at a time.

In a web.py template the first line of the file defines what data is passed to the template by web.py. So here we have $def with (form, text), which as you'll recall parallels the call we made in the GET method above. So when a client requests this page, those arguments are passed along.

The web.py templating language uses '$' symbols to denote Python expressions (and the arguments passed into the template). To use an actual '$' just escape it with '$$'. Note that it's a popular habit in jQuery to also use the dollar sign to mean the jQuery object, but we can get around that conflict simply by using 'jQuery' instead in the JavaScript. There are other ways around that but I like this method for its simplicity and how it feels the same as Python namespaces.

The head tag of the file is nothing special, it just tells us where the CSS and .js files are located (though it's important to web.py that they're in static as explained before). The JavaScript that follows needs some more explanation though:

        
        <script type="text/javascript">
                                jQuery(document).ready(function() {
                                jQuery(".button").click(function() {
                                        var input_string = $$("input#textfield").val();
                                        jQuery.ajax({
                                                type: "POST",
                                                data: {textfield : input_string},
                                                success: function(data) {
                                                jQuery('#foo').html(data).hide().fadeIn(1500);
                                                },
                                                });
                                        return false;
                                        });
                                });
        
                        </script>

It's actually pretty simple. All this does is send what's in the textfield box to the server when the button is clicked. If the action is successful (i.e. the server accepts the input data and returns it OK), jQuery replaces what's in the foo element with the data returned. This uses the ajax() function -- so the page doesn't reload (it's not really AJAX as you may realize, since there's no XML exchanged -- that's OK, I don't like XML anyway! ;) )

I'll point out some conventions that a beginner should know. Saying ".button" just refers to the element with the button class (defined in our app.py script, look above). Saying "input#textfield" refers to the input element with the CSS id of textfield (also defined in app.py).

The success function passed through ajax() is called if the action is successful; the part with hide() and then fadeIn() is just a prettier way of displaying the new text on the HTML page (otherwise, it just replaces it with no transition effect).

Lastly, returning false prevents the page from reloading.

Moving on to the body of the HTML page:

    <body>
        <br>
        <form class="form" method="post"> 
        $:form.render()
        <input class="button" type="submit" value="send"/>    
        </form>

        <br><br>
        <span id="foo">$text</span>        
    </body>
    

All we do here is enclose a rendering of the textfield and button in form tags. This isn't totally necessary, but as I discovered, without the form tags pressing return in the textfield box doesn't activate the button (i.e. you have to click on the button). Apparently you can process keyboard events with jQuery but this seemed simpler.

An additional note about $ is that you need to use $: if the expression will contain some HTML that you don't want escaped, as we do with $:form.render.

The foo span element is just a basic container that the jQuery function can replace with the new text.

To recap, what this does is display (from your browser GETting the page from the server) a HTML page with a textfield and button. When you enter text in the textfield and submit it (that is, POST it), the JavaScript on the HTML page runs, and replaces the foo element with the text processed and returned by the app.py without reloading the page. There you have it -- basic Python and AJAX!

There are some obvious improvements to be made here. First of all there's nothing stopping the user from clicking the button multiple times and sending multiple POST requests (probably not a desirable situation). There also isn't any user session setup or form validation. In any case these things are next in my list to learn, but my experience with web.py and jQuery has been great so far. I'm looking forward to more!

Also, the documentation for web.py and jQuery are good, so check those out for more information on their APIs.

I'd like to thank the members of the web.py mailing list, particularly Branko Vukelić, for their feedback on an earlier draft of this post. Naturally all errors are (most definitely) my own.

If you'd like a zipped copy of the files in this tutorial, you can get it here. Run app.py and then point your browser to http://localhost:8080 (on Windows; use the appropriate address for your setup).

reading the dictionary

for Valentine’s day

maybe this is too dumb? Oh well.

egrep ‘ing.$’ sonnets.txt

O! how thy worth with manners may I sing,
What can mine own praise to mine own self bring?
Farewell! thou art too dear for my possessing,
The charter of thy worth gives thee releasing;
For how do I hold thee but by thy granting?
And for that riches where is my deserving?
The cause of this fair gift in me is wanting,
And so my patent back again is swerving.
Thy self thou gav’st, thy own worth then not knowing,
Or me to whom thou gav’st it, else mistaking;
So thy great gift, upon misprision growing,
Comes home again, on better judgement making.
From you have I been absent in the spring,
Hath put a spirit of youth in every thing,
My love is strengthen’d, though more weak in seeming;
That love is merchandiz’d, whose rich esteeming,
Our love was new, and then but in the spring,
As Philomel in summer’s front doth sing,
Of this our time, all you prefiguring;
They had not skill enough your worth to sing:
O! ’tis the first, ’tis flattery in my seeing,
To bitter sauces did I frame my feeding;
To be diseas’d, ere that there was true needing.

Egrep for linguists.

Shakespearean sonnets.

corresponding course (#1)

One of the authors of the IFComp 2009 game Earl Grey also teaches some cool classes in NYC, some of which happen to be on elit using Python.

The Spring class started recently. Though I make it a habit to browse the UW and Hugo House class schedules for any similar kind of course (on the craft and practice of elit), I’ve never found one, so though I’m a little behind I’ve decided to follow along with this one as best I can. There’s some great material in the syllabus and the class notes. From the first class:

Suggested exercises

This is just to grep. Use a combination of the UNIX commands discussed in class (along with any other commands that you discover) to compose a text. Your “source code” for this exercise will simply consist of what you executed on the command line. Indicate what kind of source text the “program” expects, and give an example of what text it generates. Use man to discover command line options that you might not have known about (grep -i is a good one).

[matingball ~/rwet]$ grep you | tr . \\n | sort
This is just to grep. Use a combination of the UNIX commands discussed in class (along with any other commands that you discover) to compose a text. Your “source code” for this exercise will simply consist of what you executed on the command line. Indicate what kind of source text the “program” expects, and give an example of what text it generates. Use man to discover command line options that you might not have known about (grep -i is a good one).
^D
 Indicate what kind of source text the “program” expects, and give an example of what text it generates
 Use a combination of the UNIX commands discussed in class (along with any other commands that you discover) to compose a text
 Use man to discover command line options that you might not have known about (grep -i is a good one)
 Your “source code” for this exercise will simply consist of what you executed on the command line
This is just to grep
[matingball ~/rwet]$

Physical therapy. Take a text on paper–a newspaper, a restaurant menu, a book, whatever–and perform a transformation on it equivalent to the way one of the UNIX text commands we discussed transforms digital text. For example, to grep a book, you might highlight or cut out all of the lines in the book that match a particular string.

art review:

Playing text games on the web

Of course purists will say, ‘playing text games in the web browser’. Only in the last year or two have web clients for muds and interactive fiction really started to gain momentum. As far as I can tell there hasn’t been a single source that attempts to note them all in one place, so that’s what I’ll try to do here. I’ll treat IF and muds separately (though in many ways the use case isn’t that different).

Interactive Fiction:

Traditionally IF in the browser used java applets or java web start. Zplet and Zag are java interpreters for the z-machine and glulx, respectively, the former using applets and the latter web start. ZMPP is in this category as well.

While web start launches a new window, applets typically run within the browser window. For example, Jetty, a TADS 2 applet, looks like this:

But you also can style applets how you like within the page; for example, contrast the above with this game:

Over the last few years it seems like JavaScript has been superseding Java for many web applications, but JavaScript has been around for IF for a while.

That’s from Aunts and Butlers, a 2006 JavaScript IFComp game.

Of special note is that the IFDB offers plugins so that it’ll start a game automatically (using an interpreter on your local computer). In essence this is like using Java web start, but with a much greater variety of game formats available.

The IFDB is not only the IF site where you can play games; the IFwiki has a good list of sites with various web-based interpreters.

A lesser known z-machine/glulx interpreter is iffy. It’s a CGI application, so it needs a web host to run from (rather than running completely on the player’s computer).

To be honest, though, all of this is a lead up for the new generation of IF interpreters, the standard bearer of which is the z-machine’s Parchment.

The Parchment development site links to instructions on how an author can get their game running. Because Parchment uses the Google app engine, all the author needs to do is put their game file on a publically accessible computer somewhere. Of course, an author can download the Parchment package to their own host as well.

Parchment isn’t the only representative of this new breed of interpreters. Quixe is a work in progress to emulate Parchment for glulx games (not yet released). Leaflet was developed by Jay Is Games for playing IF at their site. Another Flash z-code interpreter is Flaxo.

Other interpreters in this class include ifrotz, written in Ruby and C:

:

As well as SilverGlulxe, a glulx interpreter in Silverlight:

Of special note here is Guncho, essentially a mud server written with Inform 7. As a mud server, you can connect to it with mud clients. Guncho hosts a java client on its homepage, and these work a lot like the applet and web start interpreters shown above.

Well, since I’m talking about mud servers, that’s our bridge to jump over to…

MUDS:

Web clients for muds got their start with the java applets and java web start clients just mentioned. Since many of these were made for specific games, and were an attempt in some way to compete with native clients (such as mushclient, Zmud, and so on), they often look a little fancier than comparable IF interpreters.

Also due to the server-based nature of muds, they more often have employed socket-based Flash clients for players;

That’s a souped up example of Fmud, available for free (but not open source) from the developer. Fmud is not the only Flash mud client out there, but it’s simply harder to track down these clients (compared to IF clients), and Fmud is probably the most feature complete and polished one you’ll find. Of note is Soiled, a haXe client (which compiles to Flash).

Similarly with the progression in IF from Java to JavaScript, lately there has been a progression in muds from Java and Flash toward JavaScript clients. The jMud client is mostly JavaScript with a Flash socket connection. MUDBrowser is a JavaScript based subscription service to play muds in a web browser.

There are also generic telnet clients such as anyterm that use AJAX. I even found a Firefox plugin to do a similar thing (though I couldn’t get that to work for muds very well — I think it was designed for BBSes).

The PHuDBase client is a very new php-based platform (which currently requires Google Chrome to try out).

This represents my current knowledge of what’s available; with a little more digging I know I can find more clients particular to specific muds, but I don’t think they progress beyond the examples shown here. Any other references are of course very welcome.

What can I take away from the survey? Personally I like that IF interpreters are moving toward open web standard frameworks such as JavaScript, HTML and CSS.

It’ll be interesting to see how muds approach this; by their nature muds are a little more ‘custom’ than IF games, so using platforms such as Java and Flash may make more sense, but as web services begin to integrate more and more, mobile devices proliferate, and JavaScript gets faster and easier to use, it may be the case that muds would do better going a similar route as IF. On the other hand Java and Flash are not going away anytime soon, and they do offer a richer set of options for mud client developers out of the box.

One topic I haven’t touched here is hypertext, web-based gamebooks and CYOA, boutique systems such as Twine and Twee, or the range of digital poetry and literature ‘playable’ in the browser. There obviously is a lot more to talk about when talking about ‘playing text games on the web’, and something I’d like to get to in future posts. I feel that all of these genres could learn something from the technology that each presents itself with.

Python game devs agglomerating

I found a neat little site for game development in Python, PyedPyers. Apparently it’s been around for more than a year (and this is the first time I’ve heard of it). The neat thing about it is it has some additional resources besides just a forum, such as a spot to host projects. It’s rather small at the moment and very quiet, but perhaps with a core group of some active people there some interesting stuff could happen. Check it out!

Follow

Get every new post delivered to your Inbox.