Skip to content
eladb edited this page Jun 9, 2011 · 4 revisions

Overview

restapp is a small framework (hate that word...) for creating REST web services on top of google appengine. It runs on top of the GAE webapp framework.

GET output formats

After calling the get() or query() methods, the handler will use one of the 'alt' methods to format the output. The formatting is based on the value of the 'alt' query parameter passed in the request. The default format is HTML.

These are the alt formatters implemented in the handler:

  • ?alt=html - will emit the template html named handler.html (or _handler__query.html). The template will receive a dictionary that contains the dictionaries returned by the get() or query() methods. For get(), the object will under the 'result' key.

  • ?alt=json and ?alt=jsonp&callback=cb - emits the JSON (or JSON-P) representation of the objects returned by GET or QUERY.

Usage

We will create a books service. The API of the service will be as follows:

  • GET /books will return all the books in the repository
  • GET /books/isbn - will return a specific book by ISBN
  • POST /books - will create a new book via HTTP POST

Start with a simple app.yaml which maps the /books(.*)? pattern to our handler.

- url: /books(/.*)?
  script: books.py</nowiki>

The minimum implementation will consist of defining an endpoint and running it in __main__:

import restapp
class BooksEndpoint(restapp.Endpoint):
    root_url = "/books"

def main():
    restapp.run_wsgi_restapp(BooksEndpoint)
    
if __name__ == "__main__":
    main()

Storage model:

from google.appengine.ext import db
class Book(db.Model):
    title = db.StringProperty()
    author = db.StringProperty()
    publish_year = db.IntegerProperty()
    last_update = db.DateTimeProperty(auto_now = True)
    
    @property
    def isbn(self):
        return self.key().name()</nowiki>

TODO: still work to do on the tutorial...

Full sample:

import restapp

class BooksEndpoint(restapp.Endpoint):
    root_url = "/books"

    def get(self, ctx):
        isbn = ctx.resource_path
        book = Book.get_by_key_name(isbn)
        if not book: raise restapp.errors.NotFoundError("Book with ISBN %s not found" % isbn)
        dict = restapp.utils.to_dict(book, 'isbn')
        return dict, book
    
    def query(self, ctx):
        books = Book.all()
        return [ restapp.utils.to_dict(b, 'isbn') for b in books ]
    
    def post(self, ctx):
        isbn = ctx.require('isbn')
        title = ctx.require('title')
        author = ctx.argument('author')
        publish_year = ctx.argument('publish_year')
        book = Book.get_or_insert(isbn)
        book.title = title
        book.author = author
        if publish_year: book.publish_year = int(publish_year)
        book.put()
        return isbn

def main():
    restapp.run_wsgi_restapp(BooksEndpoint)
    
if __name__ == "__main__":
    main()</nowiki>
Clone this wiki locally