web/views/json.py
changeset 10411 4ee15441f2eb
parent 10397 1ce4594f9cf4
child 10666 7f6b5f023884
equal deleted inserted replaced
10410:eb681a030699 10411:4ee15441f2eb
    18 """json export views"""
    18 """json export views"""
    19 
    19 
    20 __docformat__ = "restructuredtext en"
    20 __docformat__ = "restructuredtext en"
    21 _ = unicode
    21 _ = unicode
    22 
    22 
       
    23 from cubicweb.uilib import rest_traceback
       
    24 
    23 from cubicweb.utils import json_dumps
    25 from cubicweb.utils import json_dumps
    24 from cubicweb.predicates import any_rset, empty_rset
    26 from cubicweb.predicates import ExpectedValuePredicate, any_rset, empty_rset
    25 from cubicweb.view import EntityView, AnyRsetView
    27 from cubicweb.view import EntityView, AnyRsetView
    26 from cubicweb.web.application import anonymized_request
    28 from cubicweb.web.application import anonymized_request
    27 from cubicweb.web.views import basecontrollers
    29 from cubicweb.web.views import basecontrollers, management
    28 
    30 
    29 class JsonpController(basecontrollers.ViewController):
    31 class JsonpController(basecontrollers.ViewController):
    30     """The jsonp controller is the same as a ViewController but :
    32     """The jsonp controller is the same as a ViewController but :
    31 
    33 
    32     - anonymize request (avoid CSRF attacks)
    34     - anonymize request (avoid CSRF attacks)
    56             return self._get_json_data(rset)
    58             return self._get_json_data(rset)
    57 
    59 
    58     def _get_json_data(self, rset):
    60     def _get_json_data(self, rset):
    59         json_data = super(JsonpController, self).publish(rset)
    61         json_data = super(JsonpController, self).publish(rset)
    60         if 'callback' in self._cw.form: # jsonp
    62         if 'callback' in self._cw.form: # jsonp
    61             json_padding = self._cw.form['callback']
    63             json_padding = self._cw.form['callback'].encode('ascii')
    62             # use ``application/javascript`` is ``callback`` parameter is
    64             # use ``application/javascript`` if ``callback`` parameter is
    63             # provided, let ``application/json`` otherwise
    65             # provided, keep ``application/json`` otherwise
    64             self._cw.set_content_type('application/javascript')
    66             self._cw.set_content_type('application/javascript')
    65             json_data = '%s(%s)' % (json_padding, json_data)
    67             json_data = b'%s(%s)' % (json_padding, json_data)
    66         return json_data
    68         return json_data
    67 
    69 
    68 
    70 
    69 class JsonMixIn(object):
    71 class JsonMixIn(object):
    70     """mixin class for json views
    72     """mixin class for json views
   117             entity.cw_attr_cache.update({
   119             entity.cw_attr_cache.update({
   118                     '__cwetype__': entity.cw_etype,
   120                     '__cwetype__': entity.cw_etype,
   119                     })
   121                     })
   120             entities.append(entity)
   122             entities.append(entity)
   121         self.wdata(entities)
   123         self.wdata(entities)
       
   124 
       
   125 
       
   126 class _requested_vid(ExpectedValuePredicate):
       
   127     """predicate that checks vid parameter value
       
   128 
       
   129     It differs from ``match_view`` in that it doesn't expect a ``view``
       
   130     parameter to be given to ``select`` but will rather check
       
   131     ``req.form['vid']`` to match expected vid.
       
   132     """
       
   133     def __call__(self, cls, req, rset=None, **kwargs):
       
   134         return req.form.get('vid') in self.expected
       
   135 
       
   136 
       
   137 class JsonErrorView(JsonMixIn, management.ErrorView):
       
   138     """custom error view selected when client asks for a json view
       
   139 
       
   140     The returned json object will contain err / traceback informations.
       
   141     """
       
   142     __select__ = (management.ErrorView.__select__ &
       
   143                   _requested_vid('jsonexport', 'ejsonexport'))
       
   144 
       
   145     def call(self):
       
   146         errmsg, exclass, excinfo = self._excinfo()
       
   147         self.wdata({
       
   148             'errmsg': errmsg,
       
   149             'exclass': exclass,
       
   150             'traceback': rest_traceback(excinfo, errmsg),
       
   151             })