mirror of
https://github.com/viq/NewsBlur.git
synced 2025-04-13 09:38:09 +00:00
132 lines
No EOL
4.5 KiB
Python
132 lines
No EOL
4.5 KiB
Python
from django.core.serializers.json import DateTimeAwareJSONEncoder
|
|
from django.db import models
|
|
from django.utils.functional import Promise
|
|
from django.utils.encoding import force_unicode
|
|
from django.utils import simplejson as json
|
|
from decimal import Decimal
|
|
from django.core import serializers
|
|
from django.http import HttpResponse
|
|
from django.core.mail import mail_admins
|
|
from django.utils.translation import ugettext as _
|
|
from django.db.models.query import QuerySet
|
|
import sys
|
|
|
|
def decode(data):
|
|
return json.loads(data)
|
|
|
|
def encode(data, *args, **kwargs):
|
|
if type(data) == QuerySet: # Careful, ValuesQuerySet is a dict
|
|
# Django models
|
|
return serializers.serialize("json", data, *args, **kwargs)
|
|
else:
|
|
return json_encode(data, *args, **kwargs)
|
|
|
|
def json_encode(data, *args, **kwargs):
|
|
"""
|
|
The main issues with django's default json serializer is that properties that
|
|
had been added to an object dynamically are being ignored (and it also has
|
|
problems with some models).
|
|
"""
|
|
|
|
def _any(data):
|
|
ret = None
|
|
# Opps, we used to check if it is of type list, but that fails
|
|
# i.e. in the case of django.newforms.utils.ErrorList, which extends
|
|
# the type "list". Oh man, that was a dumb mistake!
|
|
if isinstance(data, list):
|
|
ret = _list(data)
|
|
# Same as for lists above.
|
|
elif isinstance(data, dict):
|
|
ret = _dict(data)
|
|
elif isinstance(data, Decimal):
|
|
# json.dumps() cant handle Decimal
|
|
ret = str(data)
|
|
elif isinstance(data, models.query.QuerySet):
|
|
# Actually its the same as a list ...
|
|
ret = _list(data)
|
|
elif isinstance(data, models.Model):
|
|
ret = _model(data)
|
|
# here we need to encode the string as unicode (otherwise we get utf-16 in the json-response)
|
|
elif isinstance(data, basestring):
|
|
ret = unicode(data)
|
|
# see http://code.djangoproject.com/ticket/5868
|
|
elif isinstance(data, Promise):
|
|
ret = force_unicode(data)
|
|
else:
|
|
ret = data
|
|
return ret
|
|
|
|
def _model(data):
|
|
ret = {}
|
|
# If we only have a model, we only want to encode the fields.
|
|
for f in data._meta.fields:
|
|
ret[f.attname] = _any(getattr(data, f.attname))
|
|
# And additionally encode arbitrary properties that had been added.
|
|
fields = dir(data.__class__) + ret.keys()
|
|
add_ons = [k for k in dir(data) if k not in fields]
|
|
for k in add_ons:
|
|
ret[k] = _any(getattr(data, k))
|
|
return ret
|
|
|
|
def _list(data):
|
|
ret = []
|
|
for v in data:
|
|
ret.append(_any(v))
|
|
return ret
|
|
|
|
def _dict(data):
|
|
ret = {}
|
|
for k,v in data.items():
|
|
ret[k] = _any(v)
|
|
return ret
|
|
|
|
ret = _any(data)
|
|
return json.dumps(ret, cls=DateTimeAwareJSONEncoder, ensure_ascii=False, *args, **kwargs)
|
|
|
|
def json_view(func):
|
|
def wrap(request, *a, **kw):
|
|
response = None
|
|
try:
|
|
response = func(request, *a, **kw)
|
|
if isinstance(response, dict):
|
|
response = dict(response)
|
|
if 'result' not in response:
|
|
response['result'] = 'ok'
|
|
except KeyboardInterrupt:
|
|
# Allow keyboard interrupts through for debugging.
|
|
raise
|
|
except Exception, e:
|
|
# Mail the admins with the error
|
|
exc_info = sys.exc_info()
|
|
subject = 'JSON view error: %s' % request.path
|
|
try:
|
|
request_repr = repr(request)
|
|
except:
|
|
request_repr = 'Request repr() unavailable'
|
|
import traceback
|
|
message = 'Traceback:\n%s\n\nRequest:\n%s' % (
|
|
'\n'.join(traceback.format_exception(*exc_info)),
|
|
request_repr,
|
|
)
|
|
# print message
|
|
mail_admins(subject, message, fail_silently=True)
|
|
|
|
# Come what may, we're returning JSON.
|
|
if hasattr(e, 'message'):
|
|
msg = e.message
|
|
else:
|
|
msg = _('Internal error')+': '+str(e)
|
|
response = {'result': 'error',
|
|
'text': msg}
|
|
|
|
json = json_encode(response)
|
|
return HttpResponse(json, mimetype='application/json')
|
|
return wrap
|
|
|
|
def main():
|
|
test = {1: True, 2: u"string", 3: 30}
|
|
json_test = json_encode(test)
|
|
# print test, json_test
|
|
|
|
if __name__ == '__main__':
|
|
main() |