RESTful + Controller = Restler
Restler is a base controller for Pylons projects that provides a set of default RESTful actions that can be overridden as needed.
Quick Start
This document contains info on the bleeding edge version of Restler (0.3.x). See http://code.google.com/p/restler/wiki/QuickStartZeroDotTwo for info on the previous version (0.2a18).
Install Pylons 0.9.7
easy_install Pylons==dev
Restler is developed against Pylons 0.9.7.
Install Restler
svn checkout http://restler.googlecode.com/svn/trunk/ Restler cd Restler python setup.py develop
Create a new Pylons project
paster create --template=pylons MyProject cd MyProject
Set up database engine, Session, and metadata
Not documented here. See Pylons docs.
TODO: Link to appropriate docs and/or show simple example here.
Create a base controller class
Open myproject/lib/base.py and add the following lines below the existing imports:
from restler.controller import Controller as _RestController
Next, create a new class that implements the get_db_session method:
class RestController(_RestController):
def get_db_session(self):
return myproject.model.meta.SessionWhere you define your database session object/factory is up to you. The example here is based on a model setup suggested by members of the Pylons community.
Note: The default BaseController generated by paster when creating a new Pylons project is used by the default error and template controllers, so it's probably best to leave it alone and not use it as your RESTful base controller.
Create some mapped entity classes
Every entity class needs member_name, member_title, collection_name, and collection_title class attributes.
To return JSON using the Restler controller's built-in facilities, entity classes need to define the methods to_simple_object and to_simple_collection. Restler provides an Entity base class with default implementations of these methods.
import restler.entity
class Garage(restler.entity.Entity):
member_name = 'garage'
collection_name = 'garages'
member_title = 'Garage'
collection_title = 'Garages'
# TODO: Create a SQLAlchemy `Table` object for the `Garage` class and map the
# class and table.If you're using SQLAlchemy's declarative extension, you could do something like this instead:
from sqlalchemy import MetaData
from restler.entity import EntityMeta, Entity
metadata = MetaData()
Base = declarative_base(metaclass=EntityMeta, cls=Entity, metadata=metadata)
class Garage(Base):
__tablename__ = 'garage'
__table_args__ = dict(schema='trans')
__mapper_args__ = dict(order_by='garage')Restler's EntityMeta metaclass automagically adds member_name, member_title, etc. attributes to the class.
XXX: Entity has a tiny bit of direct dependency on both SQLAlchemy (self._sa_instance_state, Column) and the declarative extension (get_column_default method uses __table__). The latter should be removed entirely. The former should be removed if at all possible.
Create a controller for each Entity class you want to expose
from myproject.model.entities.oracle.trans import Garage
from myproject.lib.base import RestController
class GaragesController(RestController):
entity = GarageMap URLs for resources/entities to controllers
In config/routing.py, add a line like this for each RESTful controller:
map.resource('garage', 'garages')Epilogue
Restler was originally extracted from the byCycle.org Trip Planner (http://bycycle.org).
Send feedback, corrections, et cetera to wyatt .DOT. lee .DOT. baldwin .AT. gmail .DOT. com or create an issue.