-
Notifications
You must be signed in to change notification settings - Fork 27
RESTful API
In order to facilitate cleaner code on the front end, we have started providing access to the database models through a RESTful API. There's a good three-part series [1] introducing REST for more information.
The endpoints are all prefixed with /rest/vX where X is the version number for the REST interface. The most recent version is 1 (since we just started).
The available resources are:
| Resource | Description |
|---|---|
/rest/v1/needs/ |
The collection of needs. Use query parameters to access a collection of needs for a particular project. Anyone may read any needs, but only project administrators or site administrators may create new needs. |
/rest/v1/needs/ID |
A particular need identified by the key ID.
Anyone may read any need, but only project
administrators or site administrators may update
or delete a need. |
/rest/v1/needs/ID/volunteers/ |
The collection of volunteers for a given need. This may only be used to create a new volunteer at the moment. Only project members can create a new volunteer for themselves. |
In general, for a given model, the endpoints are listed below. The HTTP method may either be specified as described; alternatively, for PUT and DELETE, send a POST request with an additional parameter _method
A collection resource for a given model can be accessed at the /model/ path. It represents the collection of model objects in the system. Generally, you may either retrieve the collection (or a subset), or create a new item in the collection. Upon success, this resource will give a 200 OK response.
-
GET
/model/Get a list of
modelobjects. The response will contain a representation of the identifiedmodelobjects. -
POST
/model/Creates a new
modelobject within the collection. The response will contain a representation of the createdmodelobject.
An instance resource for a given model can be accessed at the /model/ID path. It represents a particular model object instance identified by ID. Generally, you may retrieve details about the resource, make changes to the resource, or delete the resource. Upon success, this resource will return a 200 OK status. If an instance identified by ID does not exist, the resource will return a 404 Not Found response. If multiple resources exist identified by ID, the resource will return a 409 Conflict response.
-
GET
/model/IDGets a
resourceidentified byID. The response will contain a representation of the identifiedmodelobject. -
PUT
/model/IDModify the
resourceidentified byID. The response will contain an updated representation of the identifiedresourceobject. -
DELETE
/model/IDDelete the
resourceidentified byID. The response will be empty.
All resources will return the following status codes on error:
-
403 Forbiddenif the current user does not have permission to perform the requested action -
405 Method not allowedif an HTTP request method is supplied to a resource that does not support that method (e.g.PUTfor a collection).
Say you want to create resources based around projects (and collections of projects). Import the controllers.rest module, and the giveaminute.models module:
from controllers import rest from giveaminute import models
Assuming we have a model called models.Project already (which we do), we can begin to make our resources. Say we want one resource for project collectir ons. We want to be able to retrieve collections and add new projects to them. We can construct the resource using a RestController:
class ProjectCollectionResource (rest.ListInstancesMixin,
rest.CreateInstanceMixin,
rest.RestController):
model = models.Project
We use two mixins here to give the resource controller the ability to list and create resources. The other mixins available from the controllers.rest module are ReadInstanceMixin, UpdateInstanceMixin, and DeleteInstanceMixin. Note that in the default implementation, the ReadInstanceMixin and ListInstancesMixin are mutually exclusive, as they will both be blindly mapped to the GET method; you'll only ever get one behavior.
After you have created your controller, in the main module add a couple of routes identifying your resources:
ROUTES = (...
'^/rest/v1/projects/$',
'controllers.rest.ProjectCollectionResource',
'^/rest/v1/projects/(\d+)/$,
'controllers.rest.ProjectInstanceResource',
...)
That's it!
By default a resource has full read-only permission restrictions. If you provide a CreateInstanceMixin or a DeleteInstanceMixin, then no one will be able to create or delete instances. Safe, but not very useful. Use rest.ResourceAccessRules objects to differently allow and restrict access. For example, if you want your project resources to be read-only for everyone except administrative users, use the rest.NonAdminReadOnly access rules:
class ProjectCollectionResource (rest.ListInstancesMixin,
rest.CreateInstanceMixin,
rest.RestController):
model = models.Project
access_rules = rest.NonAdminReadOnly()
ResourceAccessRules classes implement permission checkers that operate on an instance of a user model (or None) and an arbitrary resource instance. The permission checking methods are:
-
can_read(user, instance)Returns
Trueif the user can read the resource -
can_create(user, instance)Returns
Trueif the user can store the resource -
can_update(user, instance)Returns
Trueif the user can modify the resource -
can_delete(user, instance)Returns
Trueif the user can delete the resource
These methods can be overridden in your own access rules class to create a custom rule system.
| [1] |
A three-part series introducing REST: |