Changes between Version 38 and Version 39 of XML-RPC

09/08/07 10:58:21 (7 years ago)




    v38 v39  
     1NOTE: All credit for this code goes to Crast in 
     3This uses SimpleXMLRPCDispatcher which is part of the standard Python lib in 2.4 (And possibly earlier versions). 
     6In 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. 
     8I've included it here.  Feel free to fiddle with it and make it your own ... All this code is '''post-mr''' 
     10Any crappy & garbage code is completely mine; I'm still learning Python so bear with me.  The hacks I added for self-documentation output are just that; any improvements to them would probably be a good thing. 
     12First, setup your to map an XML-RPC service: 
     17urlpatterns = patterns('', 
     18    # XML-RPC 
     19     (r'^xml_rpc_srv/', 'yourproject.yourapp.xmlrpc.rpc_handler'), 
     24Then, in the appropriate place, create a file called 
     29# Patchless XMLRPC Service for Django 
     30# Kind of hacky, and stolen from Crast on 
     31# Self documents as well, so if you call it from outside of an XML-RPC Client 
     32# it tells you about itself and its methods 
     34# Brendan W. McAdams <> 
     36# SimpleXMLRPCDispatcher lets us register xml-rpc calls w/o 
     37# running a full XMLRPC Server.  It's up to us to dispatch data 
     39from SimpleXMLRPCServer import SimpleXMLRPCDispatcher 
     40from django.http import HttpResponse 
     42# Create a Dispatcher; this handles the calls and translates info to function maps 
     43#dispatcher = SimpleXMLRPCDispatcher() # Python 2.4 
     44dispatcher = SimpleXMLRPCDispatcher(allow_none=False, encoding=None) # Python 2.5 
     48def rpc_handler(request): 
     49        """ 
     50        the actual handler: 
     51        if you setup your properly, all calls to the xml-rpc service 
     52        should be routed through here. 
     53        If post data is defined, it assumes it's XML-RPC and tries to process as such 
     54        Empty post assumes you're viewing from a browser and tells you about the service. 
     55        """ 
     57        response = HttpResponse() 
     58        if len(request.POST): 
     59                response.write(dispatcher._marshaled_dispatch(request.raw_post_data)) 
     60        else: 
     61                response.write("<b>This is an XML-RPC Service.</b><br>") 
     62                response.write("You need to invoke it using an XML-RPC Client!<br>") 
     63                response.write("The following methods are available:<ul>") 
     64                methods = dispatcher.system_listMethods() 
     66                for method in methods: 
     67                        # right now, my version of SimpleXMLRPCDispatcher always 
     68                        # returns "signatures not supported"... :( 
     69                        # but, in an ideal world it will tell users what args are expected 
     70                        sig = dispatcher.system_methodSignature(method) 
     72                        # this just reads your docblock, so fill it in! 
     73                        help =  dispatcher.system_methodHelp(method) 
     75                        response.write("<li><b>%s</b>: [%s] %s" % (method, sig, help)) 
     77                response.write("</ul>") 
     78                response.write('<a href=""> <img src="" border="0" alt="Made with Django." title="Made with Django."></a>') 
     80        response['Content-length'] = str(len(response.content)) 
     81        return response 
     83def multiply(a, b): 
     84        """ 
     85        Multiplication is fun! 
     86        Takes two arguments, which are multiplied together. 
     87        Returns the result of the multiplication! 
     88        """ 
     89        return a*b 
     91# you have to manually register all functions that are xml-rpc-able with the dispatcher 
     92# the dispatcher then maps the args down. 
     93# The first argument is the actual method, the second is what to call it from the XML-RPC side... 
     94dispatcher.register_function(multiply, 'multiply') 
     97That's it! 
     99You can pretty much write a standard python function in there, just be sure to register it with the dispatcher when you're done.   
     101Here's a quick and dirty client example for testing: 
     105import sys 
     106import xmlrpclib 
     107rpc_srv = xmlrpclib.ServerProxy("http://localhost:8000/xml_rpc_srv/") 
     108result = rpc_srv.multiply( int(sys.argv[1]), int(sys.argv[2])) 
     109print "%d * %d = %d" % (sys.argv[1], sys.argv[2], result) 
     112Based 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, eliminates 'out of order' argument issues and it makes the code more self-documenting). 
     114Have fun! 
     116- [  Brendan W. McAdams <>] 
     120I wrote up [ a modified version of the XML-RPC view] that uses a template for documentation. -- [ Adam Blinkinsop <>] 
     124I've taken the basics of the SimpleXMLRPCDispatcher above and have turned it into a distributable Django app, [ django_xmlrpc]. -- [ Graham Binns]