--- a/test/unittest_utils.py Tue Sep 15 16:02:07 2009 +0200
+++ b/test/unittest_utils.py Tue Sep 15 16:03:17 2009 +0200
@@ -8,7 +8,11 @@
from logilab.common.testlib import TestCase, unittest_main
-from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList
+import simplejson
+import decimal
+import datetime
+
+from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList, CubicWebJsonEncoder
class MakeUidTC(TestCase):
@@ -48,6 +52,24 @@
l.extend(extension)
yield self.assertEquals, l, expected
+class JSONEncoerTests(TestCase):
+
+ def encode(self, value):
+ return simplejson.dumps(value, cls=CubicWebJsonEncoder)
+
+ def test_encoding_dates(self):
+ self.assertEquals(self.encode(datetime.datetime(2009, 9, 9, 20, 30)),
+ '"2009/09/09 20:30:00"')
+ self.assertEquals(self.encode(datetime.date(2009, 9, 9)),
+ '"2009/09/09"')
+ self.assertEquals(self.encode(datetime.time(20, 30)),
+ '"20:30:00"')
+
+ def test_encoding_decimal(self):
+ self.assertEquals(self.encode(decimal.Decimal('1.2')), '1.2')
+
+ def test_encoding_unknown_stuff(self):
+ self.assertEquals(self.encode(TestCase), 'null')
if __name__ == '__main__':
unittest_main()
--- a/utils.py Tue Sep 15 16:02:07 2009 +0200
+++ b/utils.py Tue Sep 15 16:03:17 2009 +0200
@@ -11,10 +11,14 @@
import locale
from md5 import md5
+import datetime as pydatetime
from datetime import datetime, timedelta, date
from time import time, mktime
from random import randint, seed
from calendar import monthrange
+import decimal
+
+import simplejson
# initialize random seed from current time
seed()
@@ -348,3 +352,22 @@
return False
__answer[0] = True
return True
+
+
+class CubicWebJsonEncoder(simplejson.JSONEncoder):
+ """define a simplejson encoder to be able to encode yams std types"""
+ def default(self, obj):
+ if isinstance(obj, pydatetime.datetime):
+ return obj.strftime('%Y/%m/%d %H:%M:%S')
+ elif isinstance(obj, pydatetime.date):
+ return obj.strftime('%Y/%m/%d')
+ elif isinstance(obj, pydatetime.time):
+ return obj.strftime('%H:%M:%S')
+ elif isinstance(obj, decimal.Decimal):
+ return float(obj)
+ try:
+ return simplejson.JSONEncoder.default(self, obj)
+ except TypeError:
+ # we never ever want to fail because of an unknown type,
+ # just return None in those cases.
+ return None
--- a/web/data/cubicweb.edition.js Tue Sep 15 16:02:07 2009 +0200
+++ b/web/data/cubicweb.edition.js Tue Sep 15 16:03:17 2009 +0200
@@ -354,7 +354,7 @@
// Success
if (result[0]) {
if (onsuccess) {
- onsuccess(result[1], formid);
+ onsuccess(result, formid);
} else {
document.location.href = result[1];
}
--- a/web/views/basecontrollers.py Tue Sep 15 16:02:07 2009 +0200
+++ b/web/views/basecontrollers.py Tue Sep 15 16:03:17 2009 +0200
@@ -11,6 +11,7 @@
__docformat__ = "restructuredtext en"
from smtplib import SMTP
+import datetime
import simplejson
@@ -181,48 +182,54 @@
break
return (foreid, ex.errors)
+
def _validate_form(req, vreg):
# XXX should use the `RemoteCallFailed` mechanism
try:
ctrl = vreg['controllers'].select('edit', req=req)
except NoSelectableObject:
- return (False, {None: req._('not authorized')})
+ return (False, {None: req._('not authorized')}, None)
try:
ctrl.publish(None)
except ValidationError, ex:
- return (False, _validation_error(req, ex))
+ return (False, _validation_error(req, ex), ctrl._edited_entity)
except Redirect, ex:
+ if ctrl._edited_entity:
+ ctrl._edited_entity.complete()
try:
req.cnx.commit() # ValidationError may be raise on commit
except ValidationError, ex:
- return (False, _validation_error(req, ex))
+ return (False, _validation_error(req, ex), ctrl._edited_entity)
else:
- return (True, ex.location)
+ return (True, ex.location, ctrl._edited_entity)
except Exception, ex:
req.cnx.rollback()
req.exception('unexpected error while validating form')
- return (False, req._(str(ex).decode('utf-8')))
- return (False, '???')
+ return (False, req._(str(ex).decode('utf-8')), ctrl._edited_entity)
+ return (False, '???', None)
class FormValidatorController(Controller):
id = 'validateform'
- def response(self, domid, status, args):
+ def response(self, domid, status, args, entity):
+ callback = str(self.req.form.get('__onsuccess', 'null'))
+ errback = str(self.req.form.get('__onfailure', 'null'))
self.req.set_content_type('text/html')
- jsargs = simplejson.dumps( (status, args) )
+ jsargs = simplejson.dumps((status, args, entity), cls=CubicWebJsonEncoder)
return """<script type="text/javascript">
- window.parent.handleFormValidationResponse('%s', null, null, %s);
-</script>""" % (domid, jsargs)
+ wp = window.parent;
+ window.parent.handleFormValidationResponse('%s', %s, %s, %s);
+</script>""" % (domid, callback, errback, jsargs)
def publish(self, rset=None):
self.req.json_request = True
# XXX unclear why we have a separated controller here vs
# js_validate_form on the json controller
- status, args = _validate_form(self.req, self.vreg)
+ status, args, entity = _validate_form(self.req, self.vreg)
domid = self.req.form.get('__domid', 'entityForm').encode(
self.req.encoding)
- return self.response(domid, status, args)
+ return self.response(domid, status, args, entity)
class JSonController(Controller):