From 2e0db6c3a182f802d6753414c3ea6a8e8e42321b Mon Sep 17 00:00:00 2001 From: Jeff Knupp Date: Fri, 20 Dec 2013 14:14:24 -0500 Subject: [PATCH 1/2] Add filtering functionality through the use of query arguments --- sandman/sandman.py | 17 +++++++++++++---- sandman/test/test_sandman.py | 9 +++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/sandman/sandman.py b/sandman/sandman.py index a908945..93761d9 100644 --- a/sandman/sandman.py +++ b/sandman/sandman.py @@ -162,16 +162,24 @@ def endpoint_class(collection): raise InvalidAPIUsage(404) return cls -def retrieve_collection(collection): - """Return the resources in *collection*. +def retrieve_collection(collection, query_arguments=None): + """Return the resources in *collection*, possibly filtered by a series of + values to use in a 'where' clause search. :param string collection: a :class:`sandman.model.Model` endpoint + :param dict query_arguments: a list of filter query arguments :rtype: class:`sandman.model.Model` """ session = _get_session() cls = endpoint_class(collection) - resources = session.query(cls).all() + if query_arguments: + filters = [] + for key, value in query_arguments.items(): + filters.append(getattr(cls, key)==value) + resources = session.query(cls).filter(*filters) + else: + resources = session.query(cls).all() return resources @@ -381,7 +389,8 @@ def get_collection(collection): """ cls = endpoint_class(collection) - resources = retrieve_collection(collection) + + resources = retrieve_collection(collection, request.args) _validate(cls, request.method, resources) diff --git a/sandman/test/test_sandman.py b/sandman/test/test_sandman.py index 6abd35d..f75947a 100644 --- a/sandman/test/test_sandman.py +++ b/sandman/test/test_sandman.py @@ -31,12 +31,12 @@ def teardown_method(self, _): os.unlink(self.DB_LOCATION) self.app = None - def get_response(self, uri, status_code, has_data=True, headers=None): + def get_response(self, uri, status_code, params=None, has_data=True, headers=None): """Return the response generated from a generic GET request. Do basic validation on the response.""" if headers is None: headers = {} - response = self.app.get(uri, headers=headers) + response = self.app.get(uri, query_string=params, headers=headers) assert response.status_code == status_code if has_data: assert response.data @@ -60,6 +60,11 @@ def is_html_response(response): class TestSandmanBasicVerbs(TestSandmanBase): def test_get(self): + """Test simple HTTP GET""" + response = self.get_response('/artists', 200, params={'Name': 'AC/DC'}) + assert len(json.loads(response.data)[u'resources']) == 1 + + def test_get_with_filter(self): """Test simple HTTP GET""" response = self.get_response('/artists', 200) assert len(json.loads(response.data)[u'resources']) == 275 From 403b79bb20ab10fabb70036e534076eab2f3a37b Mon Sep 17 00:00:00 2001 From: Jeff Knupp Date: Fri, 20 Dec 2013 14:18:45 -0500 Subject: [PATCH 2/2] Update README --- README.md | 47 +++++++++++++++++------------------------------ README.rst | 48 ++++++++++++++++++------------------------------ 2 files changed, 35 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 3d51b96..33e5f30 100644 --- a/README.md +++ b/README.md @@ -40,50 +40,37 @@ register((Artist, Album, Playlist)) app.run() ``` -Let's start our new service and make a request: +Let's start our new service and make a request. While we're at it, lets make use +of Sandman's awesome filtering capability by specifying a filter term: ```zsh > python runserver.py & * Running on http://127.0.0.1:5000/ -> curl GET http://localhost:5000/artists +> curl GET "http://localhost:5000/artists?Name=AC/DC" ``` ```json ... { - "ArtistId": 273, - "Name": "C. Monteverdi, Nigel Rogers - Chiaroscuro; London Baroque; London Cornett & Sackbu", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } - ] -}, -{ - "ArtistId": 274, - "Name": "Nash Ensemble", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } - ] -}, -{ - "ArtistId": 275, - "Name": "Philip Glass Ensemble", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } + "resources": [ + { + "ArtistId": 1, + "Name": "AC/DC", + "links": [ + { + "rel": "self", + "uri": "/artists/1" + } + ] + } ] } -] ``` +All of that, including filtering/searching, is automagically available from +those 10 measly lines of code. + Oh, that's not enough? You also want a Django-style admin interface built automatically? Fine. Add one more line to the list of models to get access to this: diff --git a/README.rst b/README.rst index 36e0dfd..c9f34d7 100644 --- a/README.rst +++ b/README.rst @@ -39,49 +39,37 @@ database using **sandman**: app.run() -Let's start our new service and make a request: +Let's start our new service and make a request. While we're at it, lets +make use of Sandman's awesome filtering capability by specifying a +filter term: .. code:: zsh > python runserver.py & * Running on http://127.0.0.1:5000/ - > curl GET http://localhost:5000/artists + > curl GET "http://localhost:5000/artists?Name=AC/DC" .. code:: json ... { - "ArtistId": 273, - "Name": "C. Monteverdi, Nigel Rogers - Chiaroscuro; London Baroque; London Cornett & Sackbu", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } - ] - }, - { - "ArtistId": 274, - "Name": "Nash Ensemble", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } - ] - }, - { - "ArtistId": 275, - "Name": "Philip Glass Ensemble", - "links": [ - { - "rel": "self", - "uri": "/artists/ArtistId" - } + "resources": [ + { + "ArtistId": 1, + "Name": "AC/DC", + "links": [ + { + "rel": "self", + "uri": "/artists/1" + } + ] + } ] } - ] + +All of that, including filtering/searching, is automagically available +from those 10 measly lines of code. Oh, that's not enough? You also want a Django-style admin interface built automatically? Fine. Add one more line to the list of models to