[views] implement a custom json error view
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Tue, 16 Jun 2015 18:01:58 +0200
changeset 10390 0bbd211cf4d7
parent 10389 f9b06d03859f
child 10394 f9fc7b2a192e
[views] implement a custom json error view If the client asked for ``(e)jsonexport`` view, answer him with a json response rather than an error formatted in a big HTML blob. add a custom _requested_vid predicate. In cw 3.21, it will be deprecated in favor of ``match_form_params(vid=('jsonexport', 'ejsonexport'))``
web/views/json.py
web/views/management.py
--- a/web/views/json.py	Wed May 13 17:49:45 2015 +0200
+++ b/web/views/json.py	Tue Jun 16 18:01:58 2015 +0200
@@ -20,11 +20,13 @@
 __docformat__ = "restructuredtext en"
 _ = unicode
 
+from cubicweb.uilib import rest_traceback
+
 from cubicweb.utils import json_dumps
-from cubicweb.predicates import any_rset, empty_rset
+from cubicweb.predicates import ExpectedValuePredicate, any_rset, empty_rset
 from cubicweb.view import EntityView, AnyRsetView
 from cubicweb.web.application import anonymized_request
-from cubicweb.web.views import basecontrollers
+from cubicweb.web.views import basecontrollers, management
 
 class JsonpController(basecontrollers.ViewController):
     """The jsonp controller is the same as a ViewController but :
@@ -119,3 +121,31 @@
                     })
             entities.append(entity)
         self.wdata(entities)
+
+
+class _requested_vid(ExpectedValuePredicate):
+    """predicate that checks vid parameter value
+
+    It differs from ``match_view`` in that it doesn't expect a ``view``
+    parameter to be given to ``select`` but will rather check
+    ``req.form['vid']`` to match expected vid.
+    """
+    def __call__(self, cls, req, rset=None, **kwargs):
+        return req.form.get('vid') in self.expected
+
+
+class JsonErrorView(JsonMixIn, management.ErrorView):
+    """custom error view selected when client asks for a json view
+
+    The returned json object will contain err / traceback informations.
+    """
+    __select__ = (management.ErrorView.__select__ &
+                  _requested_vid('jsonexport', 'ejsonexport'))
+
+    def call(self):
+        errmsg, exclass, excinfo = self._excinfo()
+        self.wdata({
+            'errmsg': errmsg,
+            'exclass': exclass,
+            'traceback': rest_traceback(excinfo, errmsg),
+            })
--- a/web/views/management.py	Wed May 13 17:49:45 2015 +0200
+++ b/web/views/management.py	Tue Jun 16 18:01:58 2015 +0200
@@ -105,19 +105,24 @@
         """
         return self._cw._('an error occurred')
 
+    def _excinfo(self):
+        req = self._cw
+        ex = req.data.get('ex')
+        excinfo = req.data.get('excinfo')
+        if 'errmsg' in req.data:
+            errmsg = req.data['errmsg']
+            exclass = None
+        else:
+            errmsg = exc_message(ex, req.encoding)
+            exclass = ex.__class__.__name__
+        return errmsg, exclass, excinfo
+
     def call(self):
         req = self._cw.reset_headers()
         w = self.w
-        ex = req.data.get('ex')#_("unable to find exception information"))
-        excinfo = req.data.get('excinfo')
         title = self._cw._('an error occurred')
         w(u'<h2>%s</h2>' % title)
-        if 'errmsg' in req.data:
-            ex = req.data['errmsg']
-            exclass = None
-        else:
-            exclass = ex.__class__.__name__
-            ex = exc_message(ex, req.encoding)
+        ex, exclass, excinfo = self._excinfo()
         if excinfo is not None and self._cw.vreg.config['print-traceback']:
             if exclass is None:
                 w(u'<div class="tb">%s</div>'