Welcome to tcrudge’s documentation!

TCrudge - Simple configurable framework to create CRUDL (Create, Read, Update, Delete, List) for models based on Tornado and Peewee ORM. TCrudge is under heavy development - tons of bugs are expected. You can use it in production, but API can be broken at any moment.

Installation

Tcrudge is distributed via pypi (https://pypi.python.org/pypi/tcrudge/)

pip install tcrudge

You can manually install latest version via GitHub:

pip install git+https://github.com/CodeTeam/tcrudge.git

Example

One-file sample application:

import asyncio

import peewee
import peewee_async
from playhouse.db_url import parse
from tornado import web
from tornado.ioloop import IOLoop

from tcrudge.handlers import ApiListHandler, ApiItemHandler
from tcrudge.models import BaseModel

# Configure Tornado to use asyncio
IOLoop.configure('tornado.platform.asyncio.AsyncIOMainLoop')

# Create database
DATABASE_URL = 'postgresql://user:dbpass@pg/test'

db_param = parse(DATABASE_URL)

db = peewee_async.PooledPostgresqlDatabase(**db_param)


# CRUDL Model
class Company(BaseModel):
    name = peewee.TextField()
    active = peewee.BooleanField()

    class Meta:
        database = db


# CL Handler
class CompanyDetailHandler(ApiItemHandler):
    model_cls = Company


# RUD Handler
class CompanyListHandler(ApiListHandler):
    model_cls = Company
    default_filter = {'active': True}


app_handlers = [
    ('^/api/v1/companies/', CompanyListHandler),
    ('^/api/v1/companies/([^/]+)/', CompanyDetailHandler)
]

application = web.Application(app_handlers)

# ORM
application.objects = peewee_async.Manager(db)

with application.objects.allow_sync():
    # Creates table, if not exists
    Company.create_table(True)

application.listen(8080, '0.0.0.0')
loop = asyncio.get_event_loop()
# Start application
loop.run_forever()

Module documentation

tcrudge.exceptions module

exception tcrudge.exceptions.HTTPError(status_code=500, log_message=None, *args, **kwargs)

Bases: tornado.web.HTTPError

Custom HTTPError class Expands kwargs with body argument Usage: raise HTTPError(400, b’Something bad happened’)

tcrudge.models module

Module contains basic model class.

class tcrudge.models.BaseModel(*args, **kwargs)

Bases: peewee.Model

Basic abstract ORM model.

DoesNotExist

alias of BaseModelDoesNotExist

id = <peewee.PrimaryKeyField object>
classmethod to_schema(excluded=None)

Generates JSON schema from ORM model. User can exclude some fields from serialization, by default the only fields to exclude are pagination settings.

Parameters:excluded (list or tuple.) – Excluded parameters.
Returns:JSON schema.
Return type:dict.

tcrudge.response module

Functions to handle different response formats must receive two arguments:
  • handler: subclass of tornado.web.RequestHandler;
  • answer: dictionary with response data.

And it should return bytes.

tcrudge.response.response_json(handler, response)

Default JSON response.

Sets JSON content type to given handler.

Serializes result with JSON serializer and sends JSON as response body.

Returns:Bytes of JSONised response
Return type:bytes
tcrudge.response.response_msgpack(handler, response)

Optional MSGPACK response.

Sets MSGPACK content type to given handler.

Packs response with MSGPACK.

Returns:Bytes of MSGPACK packed response
Return type:bytes

tcrudge.handlers module

Module contains basic handlers:

  • BaseHandler - to be used for custom handlers. For instance - RPC, if you wish.
  • ApiHandler - Abstract for API handlers above.
  • ApiListHandler - Create (POST), List view (GET).
  • ApiItemHandler - detailed view (GET), Update (PUT), Delete (DELETE).
class tcrudge.handlers.ApiHandler(application, request, **kwargs)

Bases: tcrudge.handlers.BaseHandler

Base helper class for API functions. model_cls MUST be defined.

exclude_fields = ()
get_base_queryset()
get_schema_output

Maybe you’d ask: “What’s a get-schema?”

The answer is that we wanted to check input of every request method in a homologous way. So we decided to describe any input and output using JSON schema.

Schema must be a dict.

max_depth = None
model_cls

Model class must be defined. Otherwise it’ll crash a little later even if nothing seems to be accessing a model class. If you think you don’t need a model class, consider the architecture. Maybe it doesn’t fit REST. In that case use BaseHandler.

https://github.com/CodeTeam/tcrudge/issues/6

recurse = False
serialize(model)

Method to serialize a model.

By default all fields are serialized by model_to_dict. The model can be any model instance to pass through this method. It MUST be a Model instance, it won’t work for basic types containing such instances.

User have to handle it by their own hands.

Parameters:model (Model instance.) – Model instance to serialize.
Returns:serialized model.
Return type:dict
class tcrudge.handlers.ApiItemHandler(*args, **kwargs)

Bases: tcrudge.handlers.ApiHandler

Base Item API Handler. Supports R, U, D from CRUDL.

delete(item_id)

Handles DELETE request.

_delete method must be defined to handle delete logic. If method is not defined, HTTP 405 is raised.

If deletion is finished, writes to response HTTP code 200 and a message ‘Item deleted’.

Raises:HTTPError 405 if model object is not deletable.
delete_schema_input

JSON Schema to validate DELETE request body.

Returns:JSON schema for DELETE.
Return type:dict
delete_schema_output

Returns DELETE Schema, empty be default.

Return type:dict
get(item_id)

Handles GET request.

  1. Validates request.
  2. Writes serialized object of ORM model instance to response.
get_item(item_id)

Fetches item from database by PK. Result is cached in self._instance for multiple calls

Raises:HTTP 404 if no item found.
Returns:raw object if exists.
Return type:ORM model instance.
get_queryset(item_id)
get_schema_input

JSON Schema to validate DELETE request body.

Returns:GET JSON schema
Return type:dict
put(item_id)

Handles PUT request. Validates data and updates given item.

Returns serialized model.

Raises 405 in case of not updatable model (there must be _update method implemented in model class).

Raises 400 in case of violated constraints, invalid parameters and other data and integrity errors.

Raises:HTTP 405, HTTP 400.
put_schema_input

JSON Schema to validate PUT request body.

Returns:JSON schema of PUT
Return type:dict
put_schema_output

Returns PUT Schema, empty be default.

Return type:dict
class tcrudge.handlers.ApiListHandler(*args, **kwargs)

Bases: tcrudge.handlers.ApiHandler

Base List API Handler. Supports C, L from CRUDL. Handles pagination,

  • default limit is defined
  • maximum limit is defined

One can redefine that in their code.

Other pagination parameters are:

  • limit - a positive number of items to show on a single page, int.
  • offset - a positive int to define the position in result set to start with.
  • total - A boolean to define total amount of items to be put in result set or not. 1 or 0.

Those parameters can be sent as either GET parameters or HTTP headers. HTTP headers are more significant during parameters processing, but GET parameters are preferable to use as conservative way of pagination. HTTP headers are:

  • X-Limit
  • X-Offset
  • X-Total

“exclude” filter args are for pagination, you must not redefine them ever. Otherwise you’d have to also redefine the prepare method.

Some fieldnames can be added to that list. Those are fields one wishes not to be included to filters.

default_filter

Default queryset WHERE clause. Used for list queries first. One must redefine it to customize filters.

Returns:dict
default_limit = 50
default_order_by

Default queryset ORDER BY clause. Used for list queries. Order by must contain a string with a model field name.

exclude_filter_args = ['limit', 'offset', 'total']
get()

Handles GET request.

  1. Validates GET parameters using GET input schema and validator.
  2. Executes query using given query parameters.
  3. Paginates.
  4. Serializes result.
  5. Writes to response, not finishing it.
Raises:In case of bad query parameters - HTTP 400.
get_queryset(paginate=True)

Get queryset for model. Override this method to change logic.

By default it uses qs_filter and qs_order_by. All arguments for WHERE clause are passed with AND condition.

get_schema_input

JSON Schema to validate GET Url parameters. By default it contains pagination parameters as required fields. If you wish to use query filters via GET parameters, you need to redefine get_schema_input so that request with filter parameters would be valid.

In schema you must define every possible way to filter a field, you wish to be filtered, in every manner it should be filtered. For example, if you wish to filter by a field “name” so that the query returns you every object with name like given string:

{
    "type": "object",
    "additionalProperties": False,
    "properties": {
      "name__like": {"type": "string"},
      "total": {"type": "string"},
      "limit": {"type": "string"},
      "offset": {"type": "string"},
      "order_by": {"type": "string"},
    },
}

If you wish to filter by a field “created_dt” by given range:

{
    "type": "object",
    "additionalProperties": False,
    "properties": {
      "created_dt__gte": {"type": "string"},
      "created_dt__lte": {"type": "string"},
      "total": {"type": "string"},
      "limit": {"type": "string"},
      "offset": {"type": "string"},
      "order_by": {"type": "string"},
    },
}

To cut it short, you need to add parameters like “field__operator” for every field you wish to be filtered and for every operator you wish to be used.

Every schema must be a dict.

Returns:returns schema.
Return type:dict
head()

Handles HEAD request.

  1. Validates GET parameters using GET input schema and validator.
  2. Fetches total amount of items and returns it in X-Total header.
  3. Finishes response.
Raises:In case of bad query parameters - HTTPError 400.
max_limit = 100
post()

Handles POST request. Validates data and creates new item. Returns serialized object written to response.

HTTPError 405 is raised in case of not creatable model (there must be _create method implemented in model class).

HTTPError 400 is raised in case of violated constraints, invalid parameters and other data and integrity errors.

Raises:HTTPError 405, 400
post_schema_input

JSON schema of our model is generated here. Basically it is used for Create method - list handler, method POST.

Hint: Modified version of this schema can be used for Update (PUT, detail view).

Returns:JSON schema of given model_cls Model.
Return type:dict
post_schema_output

JSON Schema to validate POST request body. Abstract.

Every schema must be a dict.

Returns:dict
prepare()

Method to get and validate offset and limit params for GET REST request. Total is boolean 1 or 0.

Works for GET method only.

classmethod qs_filter(qs, flt, value, process_value=True)

Private method to set WHERE part of query. If required, Django-style filter is available via qs.filter() and peewee.DQ - this method provides joins.

Filter relational operators are: * NOT - ‘-‘, not operator, should be user as prefix * < - ‘lt’, less than * > - ‘gt’, greater than * <= - ‘lte’, less than or equal * >= - ‘gte’, greater than or equal * != - ‘ne’, not equal * LIKE - ‘like’, classic like operator * ILIKE - ‘ilike’, case-insensitive like operator * IN - ‘in’, classic in. Values should be separated by comma * ISNULL - ‘isnull’, operator to know if smth is equal to null. Use -<fieldname>__isnull for IS NOT NULL

classmethod qs_order_by(qs, value, process_value=True)

Set ORDER BY part of response.

Fields are passed in a string with commas to separate values. ‘-‘ prefix means descending order, otherwise it is ascending order.

Returns:orderbyed queryset
Return type:queryset
class tcrudge.handlers.BaseHandler(application, request, **kwargs)

Bases: tornado.web.RequestHandler

Base helper class. Provides basic handy responses.

To be used for customized handlers that don’t fit REST API recommendations.

Defines response types in relation to Accept header. Response interface is described in corresponding module.

By default, inherited handlers have callback functions for JSON and MessagePack responses.

bad_permissions()

Returns answer of access denied.

Raises:HTTPError 401
static default_callback(handler, response)

Default JSON response.

Sets JSON content type to given handler.

Serializes result with JSON serializer and sends JSON as response body.

Returns:Bytes of JSONised response
Return type:bytes
get_query_argument(name, default=<object object>, strip=True)
get_response(result=None, errors=None, **kwargs)

Method returns conventional formatted byte answer.

It gets Accept header, returns answer processed by callback.

Parameters:
  • result – contains result if succeeded
  • errors – contains errors if any
  • kwargs – other answer attributes
Returns:

byte answer of appropriate content type

Return type:

bytes

get_roles()

Gets roles. Abstract. Auth logic is up to user.

is_auth()

Validate user authorized. Abstract. Auth logic is up to user.

response(result=None, errors=None, **kwargs)

Method writes the response and finishes the request.

Parameters:
  • result – contains result if succeeded
  • errors – contains errors if any
  • kwargs – other answer attributes
response_callbacks = {'application/x-msgpack': <function response_msgpack>, 'application/json': <function response_json>}
validate(data, schema, format_checker=None, **kwargs)

Method to validate parameters. Raises HTTPError(400) with error info for invalid data.

Parameters:
Returns:

None if data is not valid. Else dict(data)

write_error(status_code, **kwargs)

Method gets traceback, writes it into response, finishes response.

Parameters:
  • status_code (int) – tornado parameter to format html, we don’t use it.
  • kwargs (dict) – in debug mode must contain exc_info.

tcrudge.decorators module

Module containing decorators.

tcrudge.decorators.perm_roles(items)

Check roles from input list. Auth logic is up to user.

tcrudge.utils package

tcrudge.utils.json module

tcrudge.utils.json.json_serial(obj)

JSON serializer for objects not serializable by default json code.

Parameters:obj (date, datetime or UUID) – object to serialize
Returns:formatted and serialized object
Return type:str

tcrudge.utils.validation module

Module for common validation tools.

tcrudge.utils.validation.prepare(handler)

Works for GET requests only

Validates the request’s GET method to define if there are X-Limit and X-Offset headers to extract them and concat with handler directly

tcrudge.utils.validation.validate_integer(val, min_value=None, max_value=None, default=None)

Validates the input val parameter.

If it is can not be converted to integer, returns default_value.

If it is less than min_value, returns min_value.

If it is greater than max_value, returns max_value.

Parameters:
  • val (int, float, digital string) – number to validate
  • min_value (int) – min value of validation range
  • max_value (int) – max value of validation range
  • default (int) – default value to return in case of exception
Returns:

None, min, max, default or result - int

Return type:

NoneType, int