Changes between Initial Version and Version 1 of XML-RPC


Ignore:
Timestamp:
May 24, 2006, 3:29:09 PM (19 years ago)
Author:
brendan.mcadams@…
Comment:

Example of how to do clean XML-RPC without patching django

Legend:

Unmodified
Added
Removed
Modified
  • XML-RPC

    v1 v1  
     1NOTE: All credit for this code goes to Crast in irc.freenode.net:#django...
     2
     3This uses SimpleXMLRPCDispatcher which is part of the standard Python lib in 2.4 (And possibly earlier versions).
     4
     5
     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.
     7
     8I've included it here.  Feel free to fiddle with it and make it your own ... All this code is '''post-mr'''
     9
     10Any 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.
     11
     12First, setup your urls.py to map an XML-RPC service:
     13
     14
     15{{{
     16urlpatterns = patterns('',
     17    # XML-RPC
     18     (r'^xml_rpc_srv/', 'yourproject.yourapp.xmlrpc.rpc_handler'),
     19)
     20}}}
     21
     22
     23Then, in the appropriate place, create a file called xmlrpc.py
     24
     25
     26{{{
     27# Patchless XMLRPC Service for Django
     28# Kind of hacky, and stolen from Crast on irc.freenode.net:#django
     29# Self documents as well, so if you call it from outside of an XML-RPC Client
     30# it tells you about itself and it's methods
     31#
     32# Brendan W. McAdams <brendan.mcadams@thewintergrp.com>
     33
     34# SimpleXMLRPCDispatcher lets us register xml-rpc calls w/o
     35# running a full XMLRPC Server.  It's up to us to dispatch data
     36
     37from SimpleXMLRPCServer import SimpleXMLRPCDispatcher
     38from django.http import HttpResponse
     39
     40# Create a Dispatcher; this handles the calls and translates info to function maps
     41dispatcher = SimpleXMLRPCDispatcher()
     42
     43
     44def rpc_handler(request):
     45        """
     46        the actual handler:
     47        if you setup your urls.py properly, all calls to the xml-rpc service
     48        should be routed through here.
     49        If post data is defined, it assumes it's XML-RPC and tries to process as such
     50        Empty post assumes you're viewing from a browser and tells you about the service.
     51        """
     52
     53        response = HttpResponse()
     54        if len(request.POST):
     55                response.write(dispatcher._marshaled_dispatch(request.raw_post_data))
     56        else:
     57                response.write("<b>This is an XML-RPC Service.</b><br>")
     58                response.write("You need to invoke it using an XML-RPC Client!<br>")
     59                response.write("The following methods are available:<ul>")
     60                methods = dispatcher.system_listMethods()
     61
     62                for method in methods:
     63                        # right now, my version of SimpleXMLRPCDispatcher always
     64                        # returns "signatures not supported"... :(
     65                        # but, in an ideal world it will tell users what args are expected
     66                        sig = dispatcher.system_methodSignature(method),
     67
     68                        # this just reads your docblock, so fill it in!
     69                        help =  dispatcher.system_methodHelp(method)
     70
     71                        response.write("<li><b>%s</b>: [%s] %s" % (method, sig, help))
     72
     73                response.write("</ul>")
     74                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>')
     75
     76        return response
     77
     78def multiply(a, b):
     79        """
     80        Multiplication is fun!
     81        Takes two arguments, which are multiplied together.
     82        Returns the result of the multiplication!
     83        """
     84        return a*b
     85
     86# you have to manually register all functions that are xml-rpc-able with the dispatcher
     87# the dispatcher then maps the args down.
     88# The first argument is the actual method, the second is what to call it from the XML-RPC side...
     89dispatcher.register_function(multiply, 'multiply')
     90}}}
     91
     92That's it!
     93
     94You can pretty much write a standard python function in there, just be sure to register it with the dispatcher when you're done. 
     95
     96Here's a quick and dirty client example for testing:
     97
     98{{{
     99import sys
     100import xmlrpclib
     101rpc_srv = xmlrpclib.ServerProxy("http://localhost:8000/xml_rpc_srv/")
     102result = rpc_srv.multiply(sys.argv[1], sys.argv[2])
     103print "%d * %d = %d" % (sys.argv[1], sys.argv[2], result)
     104}}}
     105
     106Based 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).
     107
     108Have fun!
     109
     110- [mailto:brendan.mcadams@thewintergrp.com  Brendan W. McAdams <brendan.mcadams@thewintergrp.com>]
Back to Top