Skip to content

Commit

Permalink
Add support for total number of results returned
Browse files Browse the repository at this point in the history
Also adds support for adding information to the response wrapper.
  • Loading branch information
justinabrahms committed Mar 28, 2014
1 parent 1476e42 commit edd7af2
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 13 deletions.
7 changes: 5 additions & 2 deletions ajax/endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from ajax.signals import ajax_created, ajax_deleted, ajax_updated
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
from ajax.views import EnvelopedResponse

try:
from taggit.utils import parse_tags
Expand Down Expand Up @@ -106,8 +107,10 @@ def list(self, request):
except EmptyPage:
# If page is out of range (e.g. 9999), return empty list.
page = EmptyPageResult()

return [encoder.encode(record) for record in page.object_list]

data = [encoder.encode(record) for record in page.object_list]
return EnvelopedResponse(data=data, metadata={'total': paginator.count})


def _set_tags(self, request, record):
tags = self._extract_tags(request)
Expand Down
33 changes: 27 additions & 6 deletions ajax/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@
logger = getLogger('django.request')


class EnvelopedResponse(object):
"""
Object used to contain metadata about the request that will be added to
the wrapping json structure (aka the envelope).
:param: data - The object representation that you want to return
:param: metadata - dict of information which will be merged with the
envelope.
"""
def __init__(self, data, metadata):
self.data = data
self.metadata = metadata

@json_response
def endpoint_loader(request, application, model, **kwargs):
"""Load an AJAX endpoint.
Expand Down Expand Up @@ -64,10 +77,18 @@ def endpoint_loader(request, application, model, **kwargs):
data = endpoint(request)
if isinstance(data, HttpResponse):
return data

if isinstance(data, EnvelopedResponse):
envelope = data.metadata
payload = data.data
else:
payload = {
'success': True,
'data': data,
}
return HttpResponse(json.dumps(payload, cls=DjangoJSONEncoder,
separators=(',', ':')))
envelope = {}
payload = data

envelope.update({
'success': True,
'data': payload,
})

return HttpResponse(json.dumps(envelope, cls=DjangoJSONEncoder,
separators=(',', ':')))
35 changes: 30 additions & 5 deletions tests/example/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,29 +98,54 @@ def setUp(self):

def test_list_returns_all_items(self):
results = self.list_endpoint.list(MockRequest())
self.assertEqual(len(results), Widget.objects.count())
self.assertEqual(len(results.data), Widget.objects.count())

def test_list_obeys_endpoint_pagination_amount(self):
self.list_endpoint.max_per_page = 1
results = self.list_endpoint.list(MockRequest())
self.assertEqual(len(results), 1)
self.assertEqual(len(results.data), 1)

def test_list__ajaxerror_if_can_list_isnt_set(self):
self.assertRaises(AJAXError, self.category_endpoint.list, MockRequest())

def test_out_of_range_returns_empty_list(self):
results = self.list_endpoint.list(MockRequest(current_page=99))
self.assertEqual(len(results), 0)
self.assertEqual(len(results.data), 0)

def test_request_doesnt_override_max_per_page(self):
self.list_endpoint.max_per_page = 1
results = self.list_endpoint.list(MockRequest(items_per_page=2))
self.assertEqual(len(results), 1)
self.assertEqual(len(results.data), 1)

def test_list_has_permission__default_empty(self):
Category.objects.create(title='test')

self.category_endpoint.can_list = lambda *args, **kwargs: True

results = self.category_endpoint.list(MockRequest())
self.assertEqual(0, len(results))
self.assertEqual(0, len(results.data))

def test_list_has_total(self):
self.category_endpoint.can_list = lambda *args, **kwargs: True

results = self.list_endpoint.list(MockRequest())
self.assertEqual(6, results.metadata['total'])

class ModelEndpointPostTests(TestCase):
"""
Integration test for full urls->views->endpoint->encoder (and back) cycle.
"""
def setUp(self):
for title in ['first', 'second', 'third']:
Widget.objects.create(title=title)
u = User(email='test@example.org', username='test')
u.set_password('password')
u.save()

def test_can_request_list_with_total(self):
self.client.login(username='test', password='password')

resp = self.client.post('/ajax/example/widget/list.json')
content = json.loads(resp.content)
self.assertTrue('total' in content.keys())
self.assertEquals(content['total'], 3)

0 comments on commit edd7af2

Please sign in to comment.