Advertisement
matiascelasco

Ajax decorator for Django views

Oct 31st, 2014
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.96 KB | None | 0 0
  1. from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
  2. from django.utils import simplejson as json
  3. from django.conf import settings
  4.  
  5.  
  6. class AjaxError(Exception):
  7.  
  8.     def __init__(self, message, status=200):
  9.         super(AjaxError, self).__init__(message)
  10.         self.status = status
  11.  
  12.  
  13. def ajax_view(function_view):
  14.     """
  15.    Always return a valid ajax response with status code = 200.
  16.    The decorated function just have to return a dictionary that will be
  17.    converted to JSON and that JSON will be included in the HttpResponse.
  18.    When the decorated function fails, the returned JSON will include just an
  19.    'error' attr with the description of the error. This descriptin
  20.    will be the exception message if the raised exception is an AjaxError
  21.    instance or "Internal error" otherwise.
  22.    """
  23.  
  24.     def _wrapped_view(request, *args, **kwargs):
  25.  
  26.         if not request.is_ajax():
  27.             return HttpResponseBadRequest()
  28.  
  29.         status = 200
  30.         try:
  31.             response = function_view(request, *args, **kwargs)
  32.             if type(response) == HttpResponseRedirect:
  33.                 raise AjaxError("Permission denied")
  34.             error = None
  35.         except AjaxError, e:
  36.             response = {}
  37.             error = unicode(e)
  38.             status = e.status
  39.         except Exception, e:
  40.             response = {}
  41.             error = "Internal Error"
  42.             if settings.DEBUG:
  43.                 raise
  44.         response.update({'error': error})
  45.  
  46.         return HttpResponse(
  47.             json.dumps(response if status == 200 else response['error']),
  48.             content_type='application/json; charset=utf8',
  49.             status=status,
  50.         )
  51.  
  52.     return _wrapped_view
  53.  
  54.  
  55. def get_parameter_or_ajax_error(parameters, key):
  56.     """
  57.    Intended to avoid code repetition when checking if the ajax request includes
  58.    the required parameters.
  59.    The first argument should be request.POST or request.GET
  60.    """
  61.     if not key:
  62.         raise AjaxError('"%s" is not a valid parameter name' % key)
  63.     value = parameters.get(key, None)
  64.     if value is None:
  65.         raise AjaxError('Invalid input data (%s is null)' % key)
  66.  
  67.     return value
  68.  
  69.  
  70. def get_boolean_parameter_or_ajax_error(parameters, key):
  71.     """
  72.    Same as get_parameter_or_ajax_error but for boolean values. The idea is to
  73.    avoid some known gotchas related to boolean parameters.
  74.    """
  75.     if not key:
  76.         raise AjaxError('"%s" is not a valid parameter name' % key)
  77.     value = parameters.get(key, None)
  78.     if value is None:
  79.         raise AjaxError('Invalid input data (%s is null)' % key)
  80.  
  81.     if value == 'False' or value == 'false' or value == '0' or value == 0:
  82.         value = False
  83.     elif value:
  84.         value = True
  85.     else:
  86.         value = False
  87.  
  88.     return value
  89.  
  90.  
  91. def get_list_parameter_or_ajax_error(parameters, key):
  92.     """
  93.    Same as get_parameter_or_ajax_error but for lists. The idea is to
  94.    avoid some known gotchas related to list parameters.
  95.    """
  96.     if not key:
  97.         raise AjaxError('"%s" is not a valid parameter name' % key)
  98.     value = parameters.getlist(key, None)
  99.     if value is None:
  100.         raise AjaxError('Invalid input data (%s is null)' % key)
  101.  
  102.     return value
  103.  
  104.  
  105. # Usage:
  106. # @ajax_view
  107. # @user_passes_test(lambda u: u.is_staff)
  108. # def cms_search_companies_ajax(request):
  109. #
  110. #     country_pk = get_parameter_or_ajax_error(request.GET, 'country_pk')
  111. #     city_pk = get_parameter_or_ajax_error(request.GET, 'city_pk')
  112. #     query = get_parameter_or_ajax_error(request.GET, 'query')
  113. #
  114. #     params = {}
  115. #     if city_pk:
  116. #         params['city__pk'] = city_pk
  117. #     elif country_pk:
  118. #         params['city__country__pk'] = country_pk
  119. #     if query:
  120. #         params['name__icontains'] = query
  121.  
  122.     return {
  123.         'targets': [{
  124.             'value': company.pk,
  125.             'text': company.name
  126.         } for company in Company.objects.filter(**params)]
  127.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement