Add basic support for create and update actions in API views

customer views only for now, will add more upon further testing
This commit is contained in:
Lance Edgar 2019-08-25 16:02:59 -05:00
parent 7c0d9c4f93
commit 3d3ace1c2a
2 changed files with 81 additions and 5 deletions

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2018 Lance Edgar
# Copyright © 2010-2019 Lance Edgar
#
# This file is part of Rattail.
#
@ -49,10 +49,18 @@ class CustomerView(APIMasterView):
def collection_get(self):
return self._collection_get()
@view(permission='customers.create')
def collection_post(self):
return self._collection_post()
@view(permission='customers.view')
def get(self):
return self._get()
@view(permission='customers.edit')
def post(self):
return self._post()
def includeme(config):
config.scan(__name__)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2018 Lance Edgar
# Copyright © 2010-2019 Lance Edgar
#
# This file is part of Rattail.
#
@ -219,9 +219,77 @@ class APIMasterView(APIView):
return context
def _get(self):
uuid = self.request.matchdict['uuid']
def _get(self, obj=None, uuid=None):
if not obj:
if not uuid:
uuid = self.request.matchdict['uuid']
obj = self.Session.query(self.get_model_class()).get(uuid)
if not obj:
raise self.notfound()
return {self.get_object_key(): self.normalize(obj)}
def _collection_post(self):
"""
Default method for actually processing a POST request for the
collection, aka. "create new object".
"""
# assume our data comes only from request JSON body
data = self.request.json_body
# add instance to session, and return data for it
obj = self.create_object(data)
self.Session.flush()
return self._get(obj)
def create_object(self, data):
"""
Create a new object instance and populate it with the given data.
Note that this method by default will only populate *simple* fields, so
you may need to subclass and override to add more complex field logic.
"""
# create new instance of model class
cls = self.get_model_class()
obj = cls()
# "update" new object with given data
obj = self.update_object(obj, data)
# that's all we can do here, subclass must override if more needed
self.Session.add(obj)
return obj
def _post(self, uuid=None):
"""
Default method for actually processing a POST request for an object,
aka. "update existing object".
"""
if not uuid:
uuid = self.request.matchdict['uuid']
obj = self.Session.query(self.get_model_class()).get(uuid)
if not obj:
raise self.notfound()
return {self.get_object_key(): self.normalize(obj)}
# assume our data comes only from request JSON body
data = self.request.json_body
# update and return data for object
obj = self.update_object(obj, data)
self.Session.flush()
return self._get(obj)
def update_object(self, obj, data):
"""
Update the given object instance with the given data.
Note that this method by default will only update *simple* fields, so
you may need to subclass and override to add more complex field logic.
"""
# set values for simple fields only
for key, value in data.items():
if hasattr(obj, key):
# TODO: what about datetime, decimal etc.?
setattr(obj, key, value)
# that's all we can do here, subclass must override if more needed
return obj