Reply to comment

python web-application using generators

Probably many of you have heard already about Seaside. It’s a smalltalk web framework, where you can write a web-app in a linear style:

let’s say you want to create a web-app which:

  • shows a form to the user, where he can enter a number and submit it
  • then you show him a second form, where the user can enter a second number and submit it
  • then you show the user a page which displays the sum of those 2 submitted numbers

in Seaside, you can implement it in something like this: (pseudocode)

first_num = get_number()
second_num = get_number()
display(first_num + second_num)

my language of choice is python, so i was curious if it’s possible to achieve something similar in that language. seside uses continuations to achieve this, so i turned to python generators. they allowed me to write this:

def sum_two_numbers():
    first_num = yield InputPage("enter first number:")
    second_num = yield InputPage("enter second number:")
    sum = int(first_num) + int(second_num)
    yield TextPage("the sum isresult is: %s" % sum)

the full code is below, but first some notes about it:

  • it requires python 2.5 or higher, because i use the “advanced” version of yield, which appeared in python2.5
  • this is only proof-of-concept code, and i know that it uses global-variables, ugly names, get-where-it-should-do-post etc.
  • i know Seaside does much much more (backbutton-support etc.)

the code:

#!/usr/bin/env python2.5
from wsgiref.simple_server import make_server
from cgi import parse_qs
 
 
class TextPage(object):
    def __init__(self,text):
        self.text = text
 
    def get_response_content(self):
        return '<html><body>%s</body></html>' % self.text
 
    def get_request_data(self,environ):
        return None
 
class InputPage(TextPage):
    def get_response_content(self):
        return """<html><body>%s
            <form method="get" action=".">
            <input type="text" name="data" value=""/>
            </form>
            </body></html>""" % self.text
 
    def get_request_data(self, environ):
        get_req_dict = parse_qs(environ['QUERY_STRING'])
        return get_req_dict['data'][0]
 
 
def sum_two_numbers():
    first_num = yield InputPage("enter first number:")
    second_num = yield InputPage("enter second number:")
    sum = int(first_num) + int(second_num)
    yield TextPage("the sum isresult is: %s" % sum)
 
s = sum_two_numbers()
cur_item = None
 
def simple_app(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/html')]
    start_response(status, response_headers)
 
    global cur_item
 
    if not cur_item:
        cur_item = s.next()
    else:
        cur_item = s.send(cur_item.get_request_data(environ))
 
    return [cur_item.get_response_content()]
 
 
httpd = make_server('', 8000, simple_app)
httpd.serve_forever()

i did a quick google-check about this topic (“python web framework continuations”), and only found Nevow with Wolf, which uses a less-elegant approach, probably because when it was implemented, python2.5 was not yet available. if anyone knows about other python web-frameworks that use generators, leave me a comment.

Trackback URL for this post:

http://www.nekomancer.net/trackback/153

Reply

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.