Getting Started

Installation

  • Stable releases are uploaded to pypi: https://pypi.org/project/pyramid-jsonapi/. You can install it in the usual way:

    pip install -i pyramid_jsonapi
    
  • Development releases are also uploaded to pypi. These have versions with ‘.devN’ appended, where ‘N’ is the number of commits since the stable tag. You can install the latest one (perhaps into a virtualenv for play purposes) with

    pip install --pre -i pyramid_jsonapi
    
  • See the Developing pyramid-jsonapi documentation for details.

  • Since pyramid_jsonapi is pure python, You can download the latest code from https://github.com/colinhiggs/pyramid-jsonapi and add the directory you downloaded/cloned to to your PYTHONPATH.

Generating an API From Your Models

First import the pyramid_jsonapi module and any model classes or modules which you would like to expose as API collection endpoints. In your application’s __init__.py:

import pyramid_jsonapi
from . import models

Then instantiate an api object:

pj_api = pyramid_jsonapi.PyramidJSONAPI(config, models, [get_db_session])

This is the class that encapsulates a whole API representing a set of models. The constructor has two mandatory and one optional arguments:

  • config is the usual Configurator object used in pyramid.

  • models can either be a module (as in the example above) defining classes which inherit from declarative_base() or an iterable of such classes.

  • get_dbsession (optional) should be a callable which accepts an instance of pyramid_jsonapi.CollectionViewBase and returns a sqlalchemy.orm.session.Session (or an equivalent, like a sqlalchemy.orm.scoped_session())

Once you have an instance of PyramidJSONAPI you instruct it to build endpoints (routes and views) with the method api.create_jsonapi_using_magic_and_pixie_dust() (or api.create_jsonapi()). This is deliberately a two step affair to give you the chance to manipulate certain things (like the list of available endpoints) before the endpoints are constructed:

pj_api = pyramid_jsonapi.PyramidJSONAPI(config, models)

# Do something here like add a view for OPTIONS requests.

pj_api.create_jsonapi_using_magic_and_pixie_dust()

Auto-Create Assumptions

  1. Your model classes all inherit from a base class returned by sqlalchemy’s declarative-base().

  2. Each model has a single primary_key column. This will be auto-detected and stored in __pyramid_jsonapi__ dict attr in the model.

  3. Use a separate primary key for association objects rather than the composite key defined by the left and right referenced foreign keys.

  4. You are happy to give your collection end-points the same name as the corresponding database table (can be overridden).

  5. You have defined any relationships to exposed via the API using sqlalchemy.orm.relationship() (or backref()).

  6. You are happy to expose any so defined relationship via a relationship URL.

  7. API endpoints will be provided at /api/... by default.

  8. Metadata endpoints will be provided at /metadata/... by default.

Some of those behaviours can be adjusted, see Customising the Generated API.

Trying Your API Out

You should now have a working JSON-API. A quick test. The following assumes that you have already created and set up a pyramid project in development mode (python setup.py develop in pyramid 1.6, pip install -e in pyramid 1.7).

Make sure you have activated your virtualenv:

$ source env/bin/activate

Start the server:

$ pserve your_project/development.ini

Assuming you have a collection named ‘people’ and are using the rather lovely httpie to test:

$ http http://localhost:6543/api/people

HTTP/1.1 200 OK
Content-Length: 1387
Content-Type: application/vnd.api+json; charset=UTF-8
Date: Fri, 28 Aug 2015 20:22:46 GMT
Server: waitress
{
  "data": [
    {
      "type": "people",
      "id": "1",
      "attributes": {
        "name": "alice"
      },
      "links": {
        "self": "http://localhost:6543/api/people/1"
      },
      "relationships": {
        "<some_single_relationship>": {
          "data": {"type": "<rel_type>", "id": "<some_id>"}
        }
      }
    },
    {"<another_person>"}
  ]
}

See test_project/test_project/__init__.py for a fully working __init__.py file.

You don’t need a views.py unless you have some other routes and views.

There’s also some metadata available at http://localhost:6543/metadata. pyramid_jsonapi currently includes metadata modules to produce JSONSchema and OpenAPI/Swagger. See the Metadata Modules section.

The following will fetch the JSONSchema for a successful response to a GET on the people endpoint:

$ http http://localhost:6543/metadata/JSONSchema/endpoint/people?method=get&direction=response&code=200
{
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "meta": {
            "$ref": "#/definitions/meta"
        },
        "included": {
            "type": "array",
            "uniqueItems": true,
            "description": "To reduce the number of HTTP requests, servers **MAY** allow responses that include related resources along with the requested primary resources. Such responses are called \"compound documents\".",
            "items": {
                "$ref": "#/definitions/resource"
            }
        },
        "jsonapi": {
            "$ref": "#/definitions/jsonapi"
        },
        "data": {
            "$ref": "#/definitions/people_data"
        },
        "links": {
            "allOf": [
                {
                    "$ref": "#/definitions/links"
                },
                {
                    "$ref": "#/definitions/pagination"
                }
            ],
            "description": "Link members related to the primary data."
        }
    },
    "required": [
        "data"
    ]
}