Commits

Mark Lavin committed 71d8f65

Added AJAX required mixin for lookups.

Comments (0)

Files changed (4)

selectable/base.py

 import operator
 import re
 
+from django import http
 from django.conf import settings
 from django.core.paginator import Paginator, InvalidPage, EmptyPage
 from django.core.urlresolvers import reverse
 from django.core.serializers.json import DjangoJSONEncoder
 from django.db.models import Q
-from django.http import HttpResponse
 from django.utils import simplejson as json
 from django.utils.encoding import smart_unicode
 from django.utils.translation import ugettext as _
 __all__ = (
     'LookupBase',
     'ModelLookup',
+    'AjaxRequiredMixin',
 )
 
 
 class LookupBase(object):
+    "Base class for all django-selectable lookups."
+
     form = BaseLookupForm
 
     def _name(cls):
                     'page': page_data.next_page_number()
                 })        
         content = json.dumps(data, cls=DjangoJSONEncoder, ensure_ascii=False)
-        return HttpResponse(content, content_type='application/json')    
+        return http.HttpResponse(content, content_type='application/json')    
 
 
 class ModelLookup(LookupBase):
+    "Lookup class for easily defining lookups based on Django models."
+
     model = None
     filters = {}
     search_fields = ()
             if field_name:
                 data = {field_name: value}
         return self.model(**data)
+
+
+class AjaxRequiredMixin(object):
+    "Lookup extension to require AJAX calls to the lookup view."
+
+    def results(self, request):
+        if not request.is_ajax():
+            return http.HttpResponseBadRequest()   
+        return super(AjaxRequiredMixin, self).results(request)

selectable/tests/base.py

 from django.core.urlresolvers import reverse
 from django.test import TestCase
 
-from selectable.base import ModelLookup
+from mock import Mock
+from selectable.base import ModelLookup, AjaxRequiredMixin
 from selectable.tests import Thing
 
 __all__ = (
     'ModelLookupTestCase',
     'MultiFieldLookupTestCase',
+    'AjaxRequiredLookupTestCase',
 )
 
 
         qs = lookup.get_query(request=None, term='other')
         self.assertTrue(thing.pk not in qs.values_list('id', flat=True))
         self.assertTrue(other_thing.pk in qs.values_list('id', flat=True))
+
+
+class LookupMixinTest(object):
+    "Helper for constructing lookups using a particular mixin."
+
+    lookup_mixin = object
+
+    def create_lookup_class(self):
+        return type('TestLookup', (self.lookup_mixin, self.lookup_cls), {})
+
+
+class AjaxRequiredLookupTestCase(BaseSelectableTestCase, LookupMixinTest):
+    
+    lookup_cls = SimpleModelLookup
+    lookup_mixin = AjaxRequiredMixin
+
+    def setUp(self):
+        self.lookup = self.create_lookup_class()()
+    
+    def test_ajax_call(self):
+        "Ajax call should yield a successful response"
+        request = Mock()
+        request.is_ajax = lambda: True
+        response = self.lookup.results(request)
+        self.assertTrue(response.status_code, 200)
+
+    def test_non_ajax_call(self):
+        "Non-Ajax call should yield a bad request response"
+        request = Mock()
+        request.is_ajax = lambda: False
+        response = self.lookup.results(request)
+        self.assertTrue(response.status_code, 400)
     ],
     long_description=read_file('README.rst'),
     test_suite="runtests.runtests",
+    tests_require=['mock', ],
     zip_safe=False, # because we're including media that Django needs
 )
 [testenv]
 commands = {envpython} runtests.py
 deps = django>=1.4
+    mock
 
 [testenv:docs]
 basepython = python
 [testenv:py25-1.2.X]
 basepython = python2.5
 deps = django>=1.2,<1.3
+    mock
 
 [testenv:py26-1.2.X]
 basepython = python2.6
 deps = django>=1.2,<1.3
-
+    mock
 
 [testenv:py25-1.3.X]
 basepython = python2.5
 deps = django>=1.3,<1.4
+    mock
 
 [testenv:py26-1.3.X]
 basepython = python2.6
 deps = django>=1.3,<1.4
+    mock
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.