Skip to main content

krankshaft

No Maintenance Intended

A Web API Framework.

Currently only supports Django, but designed to work for other frameworks with some modification. At some point, other framework support will be built in directly.

https://secure.travis-ci.org/dlamotte/krankshaft.png https://coveralls.io/repos/dlamotte/krankshaft/badge.png https://img.shields.io/pypi/v/krankshaft.svg Bitdeli badge

Purpose

krankshaft was designed to make the frustrating and unnecessarily complicated parts of Web APIs simple and beautiful by default. It’s built in layers that allow the programmer to easily opt-in/out of. From “Expose this model via a web api and handle all the details” to “hands off my API, I’ll opt-into the basics as I need them”.

krankshaft is meant to be a framework to build Web APIs and grow with your application.

Goals:

  • simple and concise

  • keep the simple things simple

  • enable complex APIs without getting in the way

  • HTTP return codes are important, dont abstract them away

  • fail early

  • performance

  • no global state

  • easily extendable

  • suggests a pattern, but doesnt restrict you to it

  • secure by default

Example

This is just a suggested file structure, there is no limitation here.

In app/apiv1.py:

from django.conf import settings
from krankshaft import API

apiv1 = API('v1', debug=settings.DEBUG)

In app/views.py:

from app.apiv1 import apiv1 as api

@api
def view(request):
    return api.serialize(request, 200, {
        'key': 'value'
    })

At this point, you’ll still need to wire up the common routing for your framework. In Django, it looks something like this:

In app/urls.py:

from django.conf.urls import patterns, include, url

urlpatterns += patterns('app.views',
    url('^view/$', 'view'),
)

Resource example

In app/api.py:

from django.conf import settings

api = API('v1', debug=settings.DEBUG)

@api(url='^model/(?P<id>\d+)/$')
class ModelResource(object):
    def get(self, request, id):
        ...

    def put(self, request, id):
        ...

    def delete(self, request, id):
        ...

In app/urls.py:

from django.conf.urls import patterns, include, url
from .api import api

urlpatterns = patterns('',
    url('^api/', include(api.urls)),
)

This enables clients to make GET/PUT/DELETE requests to the endpoint:

/api/v1/model/<id>/

If a POST is made, the client will receive the proper 405 response with the Allow header set to GET, PUT, DELETE.

You can customize resources even more. You can define your own routing scheme:

class ModelResource(object):
    ...
    def route(self, request, id):
        # this is approximately the default
        try:
            view = getattr(self, request.method.lower())

        except AttributeError:
            return api.response(request, 405)

        else:
            return view(request, id)

Or setup urls and multiple routes:

class ModelResource(object):
    ...

    def get_list(self, request):
        ...

    def post_list(self, request):
        ...

    def put_list(self, request):
        ...

    def delete_list(self, request):
        ...

    def query(self, request):
        if request.method != 'POST':
            return api.response(request, 405, Allow='POST')
        ...

    def route(self, suffix, request, *args, **kwargs):
        # this is approximately the default
        try:
            view = getattr(self, request.method.lower() + suffix)

        except AttributeError:
            return api.response(request, 405)

        else:
            return view(request, *args, **kwargs)

    def route_list(self, request):
        return self.route('_list', request)

    def route_object(self, request, id):
        return self.route('', request, id)

    @property
    def urls(self):
        from django.conf.urls import patterns, url
        return patterns('', [
            url(r'^model/$', api.wrap(self.route_list)),
            url(r'^model/query/$', api.wrap(self.query)),
            url(r'^model/(?P<id>\d+)/$', api.wrap(self.route_object)),
        ])

Or (instead of building your own) use the one built in:

from krankshaft.resource import DjangoModelResource
from app.models import Model
from app.api import api

@api
class ModelResource(DjangoModelResource):
    model = Model

This resource implementation should be ideal for _most_ situations, but you’re free to reimplement parts or all of it. It’s meant only as a pattern you can follow and is not required by the framework at all.

What works

  • simple authentication/authorization schemes (not OAuth at the moment)

  • serialization of primitive types respecting HTTP Accept Header

  • abort (raise-like http response return)

  • throttling

  • resource routing

  • query application (ie: ?field__startswith=something&order_by=field) with pagination support

  • deep data validation

  • Django ORM based Model Resource (with model serialization/deserialization)
    • Optimistic Concurrency Control option (version_field)

Installation

Add krankshaft to INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    'krankshaft',
)

Todo

  • auto-documenting based on doc strings (plus bootstrap interactive UI)

  • caching

  • easy-etag support

  • flask support

  • OAuth (1 and 2)

Resources

Metadata

Release files for krankshaft 0.3.18

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for krankshaft 0.3.18
File Size Uploaded Provenance
krankshaft-0.3.18.tar.gz 118.4 kB Without provenance Details

Release files / krankshaft-0.3.18.tar.gz

Download URL krankshaft-0.3.18.tar.gz
Size 118.4 kB
Tags Source
SHA-256 checksum
How to use checksums
346b28b39735dd597d3eb854e9ca8dcb80c2db7ce6039b4e46aec6d2ca40ce26
BLAKE2b-256 checksum
How to use checksums
ad330984be6758aa91c382b596779011491eda4f375444f3b1626f1442b4864f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for krankshaft 0.3.18

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page