Skip to content

API Functionality

Thomas Pollet edited this page Sep 9, 2020 · 4 revisions

Usage

The exposed API implements all JSON:API functionality:

  • CRUD
  • Relationships
  • Filtering
  • Sorting
  • Pagination
  • Resource Linkage

In addition, this functionality can be refined and extended in many different ways.

Relationships

Database object such as the User class from the demo.py example can be extended to include relationships with other objects. The demo_relationship.py contains following extension of the User class where a relationship with the Book class is implemented:

class User(SAFRSBase, db.Model):
    '''
        description: User description
    '''
    __tablename__ = 'Users'
    id = db.Column(db.String, primary_key=True)
    name = db.Column(db.String, default='')
    email = db.Column(db.String, default='')
    books = db.relationship('Book', back_populates="user")
...

A many-to-one database association is declared by the back_populates relationship argument. The Book class is simply another subclass of SAFRSBase and db.Model, similar to the previous User class:

class Book(SAFRSBase, db.Model):
    '''
        description: Book description
    '''
    __tablename__ = 'Books'
    id = db.Column(db.String, primary_key=True)
    name = db.Column(db.String, default='')
    user_id = db.Column(db.String, db.ForeignKey('Users.id'))
    user = db.relationship('User', back_populates='books')

The User.book relationship can be queried in the API through the following endpoints: Relations Swagger

  • POST adds an item to the relationship
  • DELETE removes an item from the relationship
  • GET retrieves a list of item ids

The relationship API endpoints work similarly for one-to-many relationships.

Relationship members can also be included in the response when querying an instance, by specifying the relationship name in the include query argument.

For example, to retrieve all items in the books_read relationship from the People endpoint, you may add the include=books_read url parameter:

relationship include swagger

http://thomaxxl.pythonanywhere.com/api/People/?include=books_read

To retrieve nested relationship items, you can specify the nested relationship name after the '.', to retrieve the authors of the books_read instances for instance, you can use

http://thomaxxl.pythonanywhere.com/api/People/?include=books_read.author

If you don't want any relationships to be included in the jsonapi response for an object, you can set the supports_includes class attribute to False

Filtering

The swagger shows the jsonapi filters that can be used in the url query arguments. Items with an exact match of the specified attribute value can be fetched by specifying the corresponding key-value query parameter. For example, suppose the User class, exposed at /Users has a name attribute, to retrieve all instances with the name "John", you can use a GET request to /Users?filter[name]=John.

It is also possible to use more generic filters by specifiying a JSON string

filter=[{"name":"timestamp","op":"gt","val":"2020-08-01"},{"name":"timestamp","op":"lt","val":"2020-08-02"}]

Sorting

Collection responses can be sorted on the attribute (or attribute csv list) specified in the "sort" url query argument.

e.g.

http://thomaxxl.pythonanywhere.com/api/People/?sort=name,id

Reverse sort is also possible by using a - in front of the attribute you want to sort:

http://thomaxxl.pythonanywhere.com/api/People/?sort=-name

HTTP Status Codes

HTTP status codes are used to signal success or failure of a REST operation:

  • 200 : OK
  • 201 : The request has been fulfilled and resulted in a new resource being created.
  • 204 : No Content, DELETE operation was successful
  • 400 : The services raised an exception, for example in case of invalid input
  • 500 : Internal Server Error

In case of errors( status codes 400+ ), the log file contains a stacktrace. Two custom exceptions are defined in errors.py: ValidationError and GenericError. In case of errors, the webservice will return a default HTTP status code 500 and a customizable error message, for example

{
  "error": "Failed to execute query Entity '<class 'C2_server.Image'>' has no property 'namex'"
}