Answer the question
In order to leave comments, you need to log in
What api and implementation should be for REST collections in python?
I was not satisfied with the rest frameworks that are available in python, and I'm trying to write my own in flask (although it would probably be more correct to use falcon, as it seems to me now).
At the moment I have written approximately the following implementation.
The question arose of what to do if there are collections whose elements can also contain collections, and the user does not want to receive expanded collections.
Facebook uses 'fields' in the queryset so that the user can choose which fields he needs. But what if the user wants to exclude fields in the collection one level down (one, two, any number of levels)?
Let's take this example for clarity.
/market/labels/id/products/id/reviews
So far, I see the return of the cursor for all collections without exception as the most universal option.
I tried to write something working, but it only works if you request products/id/?fields&every, field,except,reviews, and if you request products, the user will still see reviews for each product. Of course, I can write a check like "if you need to remove fields, then if the answer is a dictionary, remove the fields from the dictionary, and if the list of dictionaries, then remove the fields in each dictionary in the list", but this looks shabby and will only work one level deep . You can go through the entire tree of dictionaries and delete the fields, but then the user must specify the full paths of the fields that he needs.
<code>class ResourceInterface(object):
__metaclass__ = ABCMeta
@abstractmethod
def get_path(self):
pass
@abstractmethod
def set_path(self, path):
pass
@abstractmethod
def on_get(self, *args, **kwargs):
pass
@abstractmethod
def on_post(self, *args, **kwargs):
pass
@abstractmethod
def on_delete(self):
pass
@abstractmethod
def on_put(self):
pass
@abstractmethod
def do_put(self):
pass
@abstractmethod
def do_post(self, *args, **kwargs):
pass
@abstractmethod
# returns serializable result e.g. dict or list or primitive
def do_get(self, *args, **kwargs):
pass
@abstractmethod
def do_delete(self, *args, **kwargs):
pass
class BaseResource(ResourceInterface):
__metaclass__ = ABCMeta
def __init__(self, repository, entity_serializer, path=None):
self.entity_serializer = entity_serializer
self.repository = repository
self.path = None
self.set_path(path)
self.pickler = Pickler(unpicklable=False)
def on_put(self):
pickled_output = self.pickler.flatten(self.do_put())
return jsonpickle.json.encode(pickled_output)
def on_post(self, *args, **kwargs):
pickled_output = self.pickler.flatten(self.do_post(*args, **kwargs))
return jsonpickle.json.encode(pickled_output)
def on_get(self, *args, **kwargs):
try:
pickled_output = self.pickler.flatten(self.do_get(*args, **kwargs))
fields = request.args.get('fields')
if fields:
for field in pickled_output.keys():
if field not in fields:
del pickled_output[field]
return jsonpickle.json.encode(pickled_output)
except ResourceNotFoundError as e:
return str(e), 404
def on_delete(self, *args, **kwargs):
pickled_output = self.pickler.flatten(self.do_delete(*args, **kwargs))
return jsonpickle.json.encode(pickled_output)
def get_path(self):
return self.path
def set_path(self, path):
self.path = path
class ResourceDecorator(ResourceInterface):
def do_delete(self, *args, **kwargs):
return self.implementation.do_delete()
def do_get(self, *args, **kwargs):
return self.implementation.do_get()
def do_post(self, *args, **kwargs):
return self.implementation.do_post()
def do_put(self):
return self.implementation.do_put()
def set_path(self, path):
self.implementation.set_path(path)
def get_path(self):
return self.implementation.get_path()
def on_post(self, *args, **kwargs):
return self.implementation.on_post(args, kwargs)
def on_get(self, *args, **kwargs):
return self.implementation.on_get(args, kwargs)
def on_delete(self):
return self.implementation.on_delete()
def on_put(self):
return self.implementation.on_put()
def __init__(self, implementation):
"""
:type implementation: BaseResource
"""
self.implementation = implementation
class FieldedResourceDecorator(ResourceDecorator):
def do_get(self, *args, **kwargs):
result = super(FieldedResourceDecorator, self).do_get(*args, **kwargs)</code>
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question