Use Cornice for REST API viws

still very experimental at this point
This commit is contained in:
Lance Edgar 2018-11-03 17:13:08 -05:00
parent 31ae5eacd5
commit ad35481234
5 changed files with 51 additions and 52 deletions

View file

@ -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__)

View file

@ -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))

View file

@ -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__)

View file

@ -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__)

View file

@ -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