| Version 1 (modified by , 20 years ago) ( diff ) |
|---|
NOTE: All credit for this code goes to Crast in irc.freenode.net:#django...
This uses SimpleXMLRPCDispatcher which is part of the standard Python lib in 2.4 (And possibly earlier versions).
In discussing ways of handling XML-RPC for Django, I realised I really needed a way to do it without patching Django's code. Crast in #django came up with a great solution, which I have modified and tweaked a bit.
I've included it here. Feel free to fiddle with it and make it your own ... All this code is post-mr
Any crappy & garbage code is completely mine; I'm still learning Python so bear with me. The hacks I addded for self-documentation output are just that; any improvements to them would probably be a good thing.
First, setup your urls.py to map an XML-RPC service:
urlpatterns = patterns('',
# XML-RPC
(r'^xml_rpc_srv/', 'yourproject.yourapp.xmlrpc.rpc_handler'),
)
Then, in the appropriate place, create a file called xmlrpc.py
# Patchless XMLRPC Service for Django
# Kind of hacky, and stolen from Crast on irc.freenode.net:#django
# Self documents as well, so if you call it from outside of an XML-RPC Client
# it tells you about itself and it's methods
#
# Brendan W. McAdams <brendan.mcadams@thewintergrp.com>
# SimpleXMLRPCDispatcher lets us register xml-rpc calls w/o
# running a full XMLRPC Server. It's up to us to dispatch data
from SimpleXMLRPCServer import SimpleXMLRPCDispatcher
from django.http import HttpResponse
# Create a Dispatcher; this handles the calls and translates info to function maps
dispatcher = SimpleXMLRPCDispatcher()
def rpc_handler(request):
"""
the actual handler:
if you setup your urls.py properly, all calls to the xml-rpc service
should be routed through here.
If post data is defined, it assumes it's XML-RPC and tries to process as such
Empty post assumes you're viewing from a browser and tells you about the service.
"""
response = HttpResponse()
if len(request.POST):
response.write(dispatcher._marshaled_dispatch(request.raw_post_data))
else:
response.write("<b>This is an XML-RPC Service.</b><br>")
response.write("You need to invoke it using an XML-RPC Client!<br>")
response.write("The following methods are available:<ul>")
methods = dispatcher.system_listMethods()
for method in methods:
# right now, my version of SimpleXMLRPCDispatcher always
# returns "signatures not supported"... :(
# but, in an ideal world it will tell users what args are expected
sig = dispatcher.system_methodSignature(method),
# this just reads your docblock, so fill it in!
help = dispatcher.system_methodHelp(method)
response.write("<li><b>%s</b>: [%s] %s" % (method, sig, help))
response.write("</ul>")
response.write('<a href="http://www.djangoproject.com/"><img src="http://media.djangoproject.com/img/badges/djangomade124x25_grey.gif" border="0" alt="Made with Django." title="Made with Django."></a>')
return response
def multiply(a, b):
"""
Multiplication is fun!
Takes two arguments, which are multiplied together.
Returns the result of the multiplication!
"""
return a*b
# you have to manually register all functions that are xml-rpc-able with the dispatcher
# the dispatcher then maps the args down.
# The first argument is the actual method, the second is what to call it from the XML-RPC side...
dispatcher.register_function(multiply, 'multiply')
That's it!
You can pretty much write a standard python function in there, just be sure to register it with the dispatcher when you're done.
Here's a quick and dirty client example for testing:
import sys
import xmlrpclib
rpc_srv = xmlrpclib.ServerProxy("http://localhost:8000/xml_rpc_srv/")
result = rpc_srv.multiply(sys.argv[1], sys.argv[2])
print "%d * %d = %d" % (sys.argv[1], sys.argv[2], result)
Based on experience, I do recommend that you use Dictionaries for your args rather than long args, but I think that's personal preference (It allows named arguments and eliminates 'out of order' argument issues).
Have fun!
- Brendan W. McAdams