Permalink
Browse files

Merge branch 'feature/search' into develop

  • Loading branch information...
Jeff Knupp
Jeff Knupp committed Dec 20, 2013
2 parents 3ebae99 + 403b79b commit 37619a4ccdb2d75d629cf63644f63ebae09227cf
Showing with 55 additions and 66 deletions.
  1. +17 −30 README.md
  2. +18 −30 README.rst
  3. +13 −4 sandman/sandman.py
  4. +7 −2 sandman/test/test_sandman.py
View
@@ -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:
View
@@ -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
View
@@ -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)
@@ -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

0 comments on commit 37619a4

Please sign in to comment.