diff --git a/pyweb/djextdirect.py b/pyweb/djextdirect.py index ede756d..b1ebf7d 100644 --- a/pyweb/djextdirect.py +++ b/pyweb/djextdirect.py @@ -232,30 +232,35 @@ class Provider( object ): It handles decoding requests, calling the appropriate function (if found) and encoding the response / exceptions. """ + # First try to use request.POST, if that doesn't work check for req.raw_post_data. + # The other way round this might make more sense because the case that uses + # raw_post_data is way more common, but accessing request.POST after raw_post_data + # causes issues with Django's test client while accessing raw_post_data after + # request.POST does not. try: - rawjson = simplejson.loads( request.raw_post_data ) - - except simplejson.JSONDecodeError: - # possibly a form submit / upload + jsoninfo = { + 'action': request.POST['extAction'], + 'method': request.POST['extMethod'], + 'type': request.POST['extType'], + 'upload': request.POST['extUpload'], + 'tid': request.POST['extTID'], + } + except (MultiValueDictKeyError, KeyError), err: try: - jsoninfo = { - 'action': request.POST['extAction'], - 'method': request.POST['extMethod'], - 'type': request.POST['extType'], - 'upload': request.POST['extUpload'], - 'tid': request.POST['extTID'], - } - except (MultiValueDictKeyError, KeyError): - # malformed request + rawjson = simplejson.loads( request.raw_post_data ) + except simplejson.JSONDecodeError: return HttpResponse( simplejson.dumps({ 'type': 'exception', 'message': 'malformed request', - 'where': 'router', - "tid": tid, + 'where': unicode(err), + "tid": None, # dunno }), mimetype="text/javascript" ) else: - return self.process_form_request( request, jsoninfo ) + return self.process_normal_request( request, rawjson ) + else: + return self.process_form_request( request, jsoninfo ) + def process_normal_request( self, request, rawjson ): if not isinstance( rawjson, list ): rawjson = [rawjson] @@ -299,7 +304,7 @@ class Provider( object ): break if args: data = args - + if data is not None: datalen = len(data) else: @@ -313,7 +318,7 @@ class Provider( object ): 'where': 'Expected %d, got %d' % ( len(func.EXT_argnames), len(data) ) }) continue - + try: if data: result = func( request, *data ) @@ -478,6 +483,7 @@ class Provider( object ): 'fileUpload: ' + simplejson.dumps(hasfiles) + ',' 'defaults: { "anchor": "-20px" },' 'paramsAsHash: true,' + 'autoScroll: true,' """buttons: [{ text: "Submit", handler: this.submit, @@ -494,7 +500,10 @@ class Provider( object ): def get_form_data( self, formname, request, pk ): formcls = self.forms[formname] - instance = formcls.Meta.model.objects.get( pk=pk ) + if pk != -1: + instance = formcls.Meta.model.objects.get( pk=pk ) + else: + instance = None forminst = formcls( instance=instance ) if hasattr( forminst, "EXT_authorize" ) and \ @@ -509,7 +518,10 @@ class Provider( object ): def update_form_data( self, formname, request ): pk = request.POST['pk'] formcls = self.forms[formname] - instance = formcls.Meta.model.objects.get( pk=pk ) + if pk != -1: + instance = formcls.Meta.model.objects.get( pk=pk ) + else: + instance = None if request.POST['extUpload'] == "true": forminst = formcls( request.POST, request.FILES, instance=instance ) else: @@ -520,9 +532,11 @@ class Provider( object ): return { 'success': False, 'errors': {'': 'access denied'} } # save if either no usable validation method available or validation passes; and form.is_valid - if ( not hasattr( forminst, "EXT_validate" ) or not callable( forminst.EXT_validate ) - or forminst.EXT_validate( request ) ) \ - and forminst.is_valid(): + if ( hasattr( forminst, "EXT_validate" ) and callable( forminst.EXT_validate ) + and not forminst.EXT_validate( request ) ): + return { 'success': False, 'errors': {'': 'pre-validation failed'} } + + if forminst.is_valid(): forminst.save() return { 'success': True } else: