Resource¶
Cliquet provides a basic component to build resource oriented APIs. In most cases, the main customization consists in defining the schema of the records for this resource.
Full example¶
import colander
from cliquet import resource
from cliquet import schema
from cliquet import utils
class BookmarkSchema(resource.ResourceSchema):
url = schema.URL()
title = colander.SchemaNode(colander.String())
favorite = colander.SchemaNode(colander.Boolean(), missing=False)
device = colander.SchemaNode(colander.String(), missing='')
class Options:
readonly_fields = ('device',)
unique_fields = ('url',)
@resource.register()
class Bookmark(resource.BaseResource):
mapping = BookmarkSchema()
def process_record(self, new, old=None):
if new['device'] != old['device']:
new['device'] = self.request.headers.get('User-Agent')
return new
See the ReadingList and Kinto projects source code for real use cases.
Resource Schema¶
Override the base schema to add extra fields using the Colander API.
class Movie(ResourceSchema):
director = colander.SchemaNode(colander.String())
year = colander.SchemaNode(colander.Int(),
validator=colander.Range(min=1850))
genre = colander.SchemaNode(colander.String(),
validator=colander.OneOf(['Sci-Fi', 'Comedy']))
Resource class¶
In order to customize the resource URLs or behaviour on record processing, the resource class can be extended:
Interaction with storage¶
In order to customize the interaction of a HTTP resource with its storage, a custom collection can be plugged-in:
from cliquet import resource
class TrackedCollection(resource.Collection):
def create_record(self, record, parent_id=None, unique_fields=None):
record = super(TrackedCollection, self).create_record(record,
parent_id,
unique_fields)
trackid = index.track(record)
record['trackid'] = trackid
return record
class Payment(resource.BaseResource):
def __init__(request):
super(Payment, self).__init__(request)
self.collection = TrackedCollection(
storage=self.collection.storage,
id_generator=self.collection.id_generator,
collection_id=self.collection.collection_id,
parent_id=self.collection.parent_id,
auth=self.collection.auth)
Custom record ids¶
By default, records ids are UUID4 <http://en.wikipedia.org/wiki/Universally_unique_identifier>_.
A custom record ID generator can be set globally in Configuration, or at the resource level:
from cliquet import resource
from cliquet import utils
from cliquet.storage import generators
class MsecId(generators.Generator):
def __call__(self):
return '%s' % utils.msec_time()
@resource.register()
class Mushroom(resource.BaseResource):
def __init__(request):
super(Mushroom, self).__init__(request)
self.collection.id_generator = MsecId()
Generators objects¶
Custom Usage¶
Within views¶
In views, a request
object is available and allows to use the storage
configured in the application:
from cliquet import resource
def view(request):
registry = request.registry
flowers = resource.Collection(storage=registry.storage,
name='app:flowers')
flowers.create_record({'name': 'Jonquille', 'size': 30})
flowers.create_record({'name': 'Amapola', 'size': 18})
min_size = resource.Filter('size', 20, resource.COMPARISON.MIN)
records, total = flowers.get_records(filters=[min_size])
flowers.delete_record(records[0])
Outside views¶
Outside views, an application context has to be built from scratch.
As an example, let’s build a code that will copy a remote Kinto collection into a local storage:
from cliquet import resource, DEFAULT_SETTINGS
from pyramid import Configurator
config_local = Configurator(settings=DEFAULT_SETTINGS)
config_local.add_settings({
'cliquet.storage_backend': 'cliquet.storage.postgresql'
'cliquet.storage_url': 'postgres://user:pass@db.server.lan:5432/dbname'
})
local = resource.Collection(storage=config_local.registry.storage,
parent_id='browsing',
name='history')
config_remote = Configurator(settings=DEFAULT_SETTINGS)
config_remote.add_settings({
'cliquet.storage_backend': 'kinto.storage',
'cliquet.storage_url': 'https://cloud-storage.services.mozilla.com'
})
remote = resource.Collection(storage=config_remote.registry.storage,
parent_id='browsing',
name='history',
auth='Basic bWF0Og==')
records, total = in remote.get_records():
for record in records:
local.create_record(record)