Skip to content

Instantly share code, notes, and snippets.

@mitechie
Created April 6, 2010 00:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mitechie/357062 to your computer and use it in GitHub Desktop.
Save mitechie/357062 to your computer and use it in GitHub Desktop.
import logging
try:
import json
except ImportError:
import simplejson as json
log = logging.getLogger(__name__)
class JSONResponse(object):
"""JSONResponse provides a standard method of responding to all JSON ajax
requests.
So that we can determine success/failure, related messages, and any html
data payload we wish to send back to the client
"""
success = False
message = ""
payload = {}
def __init__(self, success=False, message=None, payload=None):
"""Create JSONResponse
Check for success, message, payload and make sure payload is a dict
object
"""
if success:
self.success = True
if message is not None:
self.message = str(message)
else:
self.message = ""
if payload is not None and isinstance(payload, dict):
self.payload = payload
else:
self.payload = {}
def jsonify(self):
"""Return a json string of the response """
return json.dumps(self.dict_response())
def json_response(self, response):
"""Return a json response with headers set manually
If we want to combine a single json/html response in one controller
we can't use the jsonify decorator. We need to do the work that the
jsonify decorator does in here
"""
response.headers['Content-Type'] = 'application/json'
return self.jsonify()
def dict_response(self):
"""Build a dictionary of the response object """
return {"success": self.success,
"message": self.message,
"payload": self.payload}
from decorator import decorator
def mijson():
"""Action decorator that formats output for JSON
Given a function that will return content, this decorator will turn
the result into JSON, with a content-type of 'application/json' and
output it.
adds a method to the controller
self.accepts_json()
It checks if the request comes in accepting json and returns a JSONResponse
object pulling from:
self.json.success
self.json.message
self.json.payload
returned html content is placed into json.payload.html
Otherwise it just returns the html output returned.
A template variable is set so that the template can conditionaly inherit
or not
c.request_ajax = Bool
Sample Controller:
@myjson()
def pause(self, id):
result = SomeObj.pause()
if result:
self.json.success = True
self.json.message = 'Paused'
else:
self.json.success = False
self.json.message = 'Failed'
self.json.payload['job_id'] = id
return '<h1>Result was: %s</h1>' % message
Response:
{'success': true,
'message': 'Paused',
'payload': {'html': '<h1>Result was: Paused</h1>'}}
"""
def wrapper(func, self, *args, **kwargs):
request = self._py_object.request
response = self._py_object.response
def controller_accepts_json():
return 'application/json' in request.headers.get('accept', '')
is_json = False
self._py_object.c.request_ajax = False
self.accepts_json = controller_accepts_json
# go ahead and put this on the controller
# but we'll only use it if this is a json request
self.json = JSONResponse()
self.json.success = False
self.json.message = ""
self.json.payload = {}
if self.accepts_json():
is_json = True
# let the template know it's an ajax request
self._py_object.c.request_ajax = True
html = func(self, *args, **kwargs)
if is_json:
response.headers['Content-Type'] = 'application/json'
# grab the returned html content and place it in the payload under the
# key html
self.json.payload['html'] = html
log.debug("Returning JSON wrapped action output")
return self.json.jsonify()
else:
return html
return func(self, *args, **kwargs)
return decorator(wrapper)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment