Note: This is a testing middleware. This snippets may be changed frequently later.
What's it
Sometimes I thought thow to easy the output data into another format, except html format. One way, you can use decorator, just like:
@render_template(template='xxx')
def viewfunc(request,...):
And the output data of viewfunc should be pure data. And if want to output json format, you should change the decorator to:
@json_response
def viewfunc(request,...):
I think it's not difficult. But if we can make it easier? Of cause, using middleware.
So you can see the code of process_response
, it'll judge the response object first, if it's an instance of HttpResponse, then directly return it. If it's not, then get the format of requst, if it's json
format, then use json_response() to render the result.
How to setup request.format
? In process_request
you and see, if the request.REQUEST
has a format
(you can setup it in settings.py with FORMAT_STRING option), then the request.format
will be set as it. If there is not a such key, then the default will be json
. So in your view code, you can just return a python variable, this middleware will automatically render this python variable into json format data and return.
For 0.2 it support xml-rpc. But it's very different from common implementation. For server url, you just need put the same url as the normal url, for example:
http://localhost:8000/booklist/ajax_list/?format=xmlrpc
Notice that the format is 'xmlrpc'. A text client program is:
from xmlrpclib import ServerProxy
server = ServerProxy("http://localhost:8000/booklist/ajax_list/?format=xmlrpc", verbose=True)
print server.booklist({'name':'limodou'})
And the method 'booklist' of server is useless, because the url has include the really view function, so you can use any name after server
. And for parameters of the method, you should use a dict, and this dict will automatically convert into request.POST item. For above example, {'name':'limodou'}
, you can visit it via request.POST['name']
.
For html
format, you can register a format_processor
callable object in request
object. And middleware will use this callable object if the format is html
.
Intall
Because the view function may return non-HttpResponse object, so this middleware should be installed at the end of MIDDLEWARE_CLASSES sections, so that the process_response
of this middleware can be invoked at the first time before others middlewares.
And I also think this mechanism can be extended later, for example support xml-rpc, template render later, etc, but I have not implemented them, just a thought.
Options
FORMAT_STRING used for specify the key name of format variable pair in QUERY_STRING or POST data, if you don't set it in settings.py, default is 'format'. DEFAYLT_FORMAT used for default format, if you don't set it in settings.py, default is 'json'.
Reference
Snippets 8 ajax protocol for data for json_response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # Author: [email protected]
# version: 0.2
# Format the request and response from/to json and other format
#
# Update:
# 0.1 support json format
# 0.2 support xmlrpc, html format
#
from django.http import HttpResponse
from utils.ajax import json_response
from django.conf import settings
class FormatMiddleware(object):
def process_request(self, request):
format_string = getattr(settings, 'FORMAT_STRING', 'format')
format = request.GET.get(format_string, '')
if format:
request.format = format.lower() #could be "json", "xmlrpc", etc
else:
request.format = getattr(settings, 'DEFAULT_FORMAT', 'json')
if request.format == 'xmlrpc':
import xmlrpclib
p, u = xmlrpclib.getparser()
p.feed(request.raw_post_data)
p.close()
args = u.close()
if len(args) > 0:
args = args[0]
if not isinstance(args, dict):
xml = xmlrpclib.dumps(xmlrpclib.Fault(-32400, 'system error: %s' % 'Arguments should be a dict'), methodresponse=1)
return HttpResponse(xml, mimetype='text/xml; charset=utf-8')
old = request.POST._mutable
request.POST._mutable = True
for k, v in args.items():
request.POST[k] = v
request.POST._mutable = old
def process_response(self, request, response):
if isinstance(response, HttpResponse):
return response
elif request.format == 'json':
return json_response(response)
elif request.format == 'xmlrpc':
import xmlrpclib
try:
xml = xmlrpclib.dumps((response,), methodresponse=1)
except Exception, e:
xml = xmlrpclib.dumps(xmlrpclib.Fault(-32400, 'system error: %s' % e), methodresponse=1)
return HttpResponse(xml, mimetype='text/xml; charset=utf-8')
elif request.format == 'html':
if hasattr(request, 'format_processor'):
return request.format_processor(response)
else:
return HttpResponse(response)
raise Exception, 'Not support this format [%s]' % request.format
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 3 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 4 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
Please login first before commenting.