Practical notes of RESTful API design

Coding Style in RESTful:

JSON: JavaScript naming conventions: camelCase
Rest clients in Java: camelCase
Rest clients in Python and Ruby: snake_case

RESTful Mapping:

GET /customers => Retrieves a list of customers
GET /customers/{id} => Retrieves a specific customer with id.
GET /customers/5

POST /customers => Creates a new customer

PUT /customers/{id} => Updates customer with id.
PUT /customers/5

PATCH /customers/{id} => Partially updates customer with id.
PATCH /customers/5

DELETE /customers/{id} => Deletes customer with id.
DELETE /customers/5

RESTful Mapping with Relations:

GET /customers/{id}/orders => Retrieves list of orders for customer with id.
GET /customers/5/orders
GET /customers/{id}/orders/{id} => Retrieves order with id for customer with id.
GET /customers/5/orders/23

POST /customers/{id}/orders => Creates a new order in customer with id.
POST /customers/5/orders

PUT /customers/{id}/orders/{id} => Updates order with id for customer with id.
PUT /customers/5/orders/23

PATCH /customers/{id}/orders/{id} => Partially updates order with id for customer with id.
PATCH /customers/5/orders/23

DELETE /customers/{id}/orders/{id} => Deletes order with id for customer with id.
DELETE /customers/5/orders/23

RESTful Mapping with Parameters:

Filtering:

GET /customers?key=value => Retrieves list of customers with key value query parameter.
GET /customers?state=active => Here, state is a query parameter that implements a filter.

Sorting:

GET /customers?sort=value => Retrieves a list of customers with sort parameter.
GET /customers?sort=last_name

GET /customers?sort=value1, value2 => Sort parameter with list of comma separated fields.
GET /customers?sort=last_name, created_at

GET /customers?sort=last_name&dir=DESC => Sorting with two parameters.

Searching:

GET /customers/recently_registered => Simple query.
GET /customers?q=Berlin&state=active&sort=last_name&dir=DESC => Complex query with search, state, sort, dir parameters.

Paging:

GET /customers?page=3&per_page=20 => Paging with parameters.
GET /customers/search/name_starts_with?name=K&sort=name&dir=desc => Paging and sorting with parameters.

Pyramid framework tips : WebHelpers html tags and Paginate

WebHelpers has many useful functions. WebHelpers html tags and paginate are very useful for Pyramid Applications.Some features are not compatible with Pyramid framework, please see documentations.

WebHelpers in Pyramid Applications: install WebHelpers with easy_install:

$ easy_install WebHelpers

In Pyramid Application in __init__.py:

def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
  ...
  config.add_subscriber(add_renderer_globals, BeforeRender)
  ...

In helpers.py module:

  # your helpers imports
  from webhelpers.html.tags import *

In subscribers.py module:

def add_renderer_globals(event):
    """ add helpers """
    event['h'] = helpers

In Mako Templates:

  ## text input
  ${h.text("name", model.name, class_ = "large", maxlength="100")}

How to use WebHelpers Paginate with SQLAlchemy?
In your controller code:

@view_config(route_name="category_list", renderer="category/list.html")
def list(request):
    """categories list """
    ...
    # db query
    dbsession = DBSession()
    query = dbsession.query(Customer)

    # paginate
    page_url = paginate.PageURL_WebOb(request)
    customers = Page(query,
                     page=int(request.params.get("page", 1)),
                     items_per_page=10,
                     url=page_url)

    return {"customers": customers}

Paginate format in Mako Templates:

<div class="pager">
  <% link_attr={"class": "btn small"} %>
  <% curpage_attr={"class": "btn primary small disabled"} %>
  <% dotdot_attr={"class": "btn small disabled"} %>
  ${customers.pager(format="$link_previous ~2~ $link_next",
    symbol_previous="«",
    symbol_next="»",
    link_attr=link_attr,
    curpage_attr=curpage_attr,
    dotdot_attr=dotdot_attr)}
</div>

paginate

I am using Bootstrap from Twitter as css framework.