Use Cornice for REST API viws
still very experimental at this point
This commit is contained in:
parent
31ae5eacd5
commit
ad35481234
|
@ -28,9 +28,12 @@ from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
|
from cornice.resource import resource
|
||||||
|
|
||||||
from tailbone.api import APIMasterView
|
from tailbone.api import APIMasterView
|
||||||
|
|
||||||
|
|
||||||
|
@resource(collection_path='/api/customers', path='/api/customer/{uuid}')
|
||||||
class CustomerView(APIMasterView):
|
class CustomerView(APIMasterView):
|
||||||
|
|
||||||
model_class = model.Customer
|
model_class = model.Customer
|
||||||
|
@ -43,4 +46,4 @@ class CustomerView(APIMasterView):
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
CustomerView.defaults(config)
|
config.scan(__name__)
|
||||||
|
|
|
@ -33,6 +33,15 @@ from tailbone.db import Session
|
||||||
|
|
||||||
|
|
||||||
class APIMasterView(APIView):
|
class APIMasterView(APIView):
|
||||||
|
"""
|
||||||
|
Base class for data model REST API views.
|
||||||
|
"""
|
||||||
|
allow_get = True
|
||||||
|
allow_collection_get = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Session(self):
|
||||||
|
return Session
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_model_class(cls):
|
def get_model_class(cls):
|
||||||
|
@ -41,48 +50,34 @@ class APIMasterView(APIView):
|
||||||
raise NotImplementedError("must set `model_class` for {}".format(cls.__name__))
|
raise NotImplementedError("must set `model_class` for {}".format(cls.__name__))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_model_key(cls):
|
def get_normalized_model_name(cls):
|
||||||
if hasattr(cls, 'model_key'):
|
if hasattr(cls, 'normalized_model_name'):
|
||||||
return cls.model_name
|
return cls.normalized_model_name
|
||||||
return cls.get_model_class().__name__.lower()
|
return cls.get_model_class().__name__.lower()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_model_key_plural(cls):
|
def get_object_key(cls):
|
||||||
if hasattr(cls, 'model_key_plural'):
|
if hasattr(cls, 'object_key'):
|
||||||
return cls.model_key_plural
|
return cls.object_key
|
||||||
return '{}s'.format(cls.get_model_key())
|
return cls.get_normalized_model_name()
|
||||||
|
# raise NotImplementedError("must set `object_key` for {}".format(cls.__name__))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_route_prefix(cls):
|
def get_collection_key(cls):
|
||||||
if hasattr(cls, 'route_prefix'):
|
if hasattr(cls, 'collection_key'):
|
||||||
return cls.route_prefix
|
return cls.collection_key
|
||||||
return 'api.{}'.format(cls.get_model_key_plural())
|
return '{}s'.format(cls.get_object_key())
|
||||||
|
# raise NotImplementedError("must set `collection_key` for {}".format(cls.__name__))
|
||||||
|
|
||||||
@classmethod
|
def collection_get(self):
|
||||||
def get_permission_prefix(cls):
|
cls = self.get_model_class()
|
||||||
if hasattr(cls, 'permission_prefix'):
|
objects = self.Session.query(cls)
|
||||||
return cls.permission_prefix
|
|
||||||
return cls.get_model_key_plural()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_url_prefix(cls):
|
|
||||||
if hasattr(cls, 'url_prefix'):
|
|
||||||
return cls.url_prefix
|
|
||||||
return '/api/{}'.format(cls.get_model_key_plural())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def Session(self):
|
|
||||||
return Session
|
|
||||||
|
|
||||||
@api
|
|
||||||
def index(self):
|
|
||||||
objects = self.Session.query(self.model_class)
|
|
||||||
|
|
||||||
sort = self.request.params.get('sort')
|
sort = self.request.params.get('sort')
|
||||||
if sort:
|
if sort:
|
||||||
# TODO: this is fragile, but what to do if bad params?
|
# TODO: this is fragile, but what to do if bad params?
|
||||||
sortkey, sortdir = sort.split('|')
|
sortkey, sortdir = sort.split('|')
|
||||||
sortkey = getattr(self.model_class, sortkey)
|
sortkey = getattr(cls, sortkey)
|
||||||
objects = objects.order_by(getattr(sortkey, sortdir)())
|
objects = objects.order_by(getattr(sortkey, sortdir)())
|
||||||
|
|
||||||
# NOTE: we only page results if sorting is in effect, otherwise
|
# NOTE: we only page results if sorting is in effect, otherwise
|
||||||
|
@ -94,19 +89,12 @@ class APIMasterView(APIView):
|
||||||
per_page = int(per_page)
|
per_page = int(per_page)
|
||||||
objects = SqlalchemyOrmPage(objects, items_per_page=per_page, page=page)
|
objects = SqlalchemyOrmPage(objects, items_per_page=per_page, page=page)
|
||||||
|
|
||||||
data = [self.normalize(obj) for obj in objects]
|
objects = [self.normalize(obj) for obj in objects]
|
||||||
return data
|
return {self.get_collection_key(): objects}
|
||||||
|
|
||||||
def normalize(self, obj):
|
def get(self):
|
||||||
raise NotImplementedError("must implement `normalize()` method for: {}".format(self.__class__.__name__))
|
uuid = self.request.matchdict['uuid']
|
||||||
|
obj = self.Session.query(self.get_model_class()).get(uuid)
|
||||||
@classmethod
|
if not obj:
|
||||||
def defaults(cls, config):
|
raise self.notfound()
|
||||||
route_prefix = cls.get_route_prefix()
|
return {self.get_object_key(): self.normalize(obj)}
|
||||||
url_prefix = cls.get_url_prefix()
|
|
||||||
permission_prefix = cls.get_permission_prefix()
|
|
||||||
|
|
||||||
# index
|
|
||||||
config.add_route(route_prefix, '{}/'.format(url_prefix), request_method='GET')
|
|
||||||
config.add_view(cls, attr='index', route_name=route_prefix,
|
|
||||||
renderer='json', permission='{}.list'.format(permission_prefix))
|
|
||||||
|
|
|
@ -30,11 +30,16 @@ import six
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
|
from cornice.resource import resource
|
||||||
|
|
||||||
from tailbone.api import APIMasterView
|
from tailbone.api import APIMasterView
|
||||||
|
|
||||||
|
|
||||||
class UpgradeView(APIMasterView):
|
@resource(collection_path='/api/upgrades', path='/api/upgrades/{uuid}')
|
||||||
|
class UpgradeAPIView(APIMasterView):
|
||||||
|
"""
|
||||||
|
REST API views for Upgrade model.
|
||||||
|
"""
|
||||||
model_class = model.Upgrade
|
model_class = model.Upgrade
|
||||||
|
|
||||||
def normalize(self, upgrade):
|
def normalize(self, upgrade):
|
||||||
|
@ -54,4 +59,4 @@ class UpgradeView(APIMasterView):
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
UpgradeView.defaults(config)
|
config.scan(__name__)
|
||||||
|
|
|
@ -30,9 +30,12 @@ import six
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
|
from cornice.resource import resource
|
||||||
|
|
||||||
from tailbone.api import APIMasterView
|
from tailbone.api import APIMasterView
|
||||||
|
|
||||||
|
|
||||||
|
@resource(collection_path='/api/users', path='/api/users/{uuid}')
|
||||||
class UserView(APIMasterView):
|
class UserView(APIMasterView):
|
||||||
|
|
||||||
model_class = model.User
|
model_class = model.User
|
||||||
|
@ -45,4 +48,4 @@ class UserView(APIMasterView):
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
UserView.defaults(config)
|
config.scan(__name__)
|
||||||
|
|
|
@ -46,7 +46,7 @@ class View(object):
|
||||||
Base class for all class-based views.
|
Base class for all class-based views.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, request):
|
def __init__(self, request, context=None):
|
||||||
self.request = request
|
self.request = request
|
||||||
|
|
||||||
# if user becomes inactive while logged in, log them out
|
# if user becomes inactive while logged in, log them out
|
||||||
|
|
Loading…
Reference in a new issue