Python REST service using web.py

First off, run either of the following commands from PyCharm’s Terminal window (or the command line, ofcourse).

pip install web.py
# or
easy_install web.py

From PyCharm you can also go to File | Settings, then locate Project Interpreter, for your project. Here you can press the + button, search for web.py then press the Install Package button.

If we take the Getting Started code from the web.py website and place into a .py file

import web

urls = (
    '/(.*)', 'hello'
)
app = web.application(urls, globals())


class hello:
    def GET(self, name):
        if not name:
            name = 'World'
        return 'Hello, ' + name + '!'


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

Run this and you should see the output http://0.0.0.0:8080. Now, from your preferred web browser type http://localhost:8080. The default result will be “Hello hello!” if you now type http://localhost:8080/PutridParrot you’ll see “Hello PutridParrot!”.

So what’s happening…?

urls = (
    '/(.*)', 'hello'
)
app = web.application(urls, globals())

The web.application creates a web applications with the supplied url’s and the classes that each url maps to. In this instance all url’s map to the hello class. Now the hello class is

class hello:
    def GET(self, name):
        if not name:
            name = 'World'
        return 'Hello, ' + name + '!'

So this class takes all url’s and defines a function for each HTTP method accepts, the case maps to that sent via the browser, hence is uppercase GET (if you make a mistake here you’ll see a Method Not Allowed error from your REST service).

Our GET method takes an argument, in the case of http://localhost:8080/PutridParrot this argument is Putridparrot. If no argument is supplied the code sets name to ‘World’. You get the idea.

Finally we need to run the service application, hence the code

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

Templating

So this is all well and good, but the output is plain text, what if we are serving web pages, it’d be a lot better to be able to write HTML and embed our Python code in it, like PHP, ASP etc.

web.py includes a templating capability, so if we create a folder for our templates (let’s call it templates) off of our service source. Then add an HTML file, let’s call it index.html, now remove the HTML from this and replace with

$def with(name)

$if name:
   Hello <em>$name</em>
$else:
   Hello <em>World</em>

We’ve got the first line as $def with(name) which basically states that our template is called with the variable name which we then use within the rest of the template. The $ obviously preceeds our Python statements, but other than that it’s probably pretty obvious what’s going on here and fairly standard looking for Python.

Now change our python source to look like this

import web

urls = (
    '/(.*)', 'index'
)

render = web.template.render('templates/')

class index:
    def GET(self, name):
        return render.index(name)


if __name__ == "__main__":
    app = web.application(urls, globals())
    app.run()

We need to tell web.py where our templates reside, hence the line

render = web.template.render('templates/')

Now I’ve changed the class etc. to be our index class, this wasn’t necessary as render.index maps to our HTML file name, but I figured I’d try and make things more like a real world application.