Code

NOTE: All credit for this code goes to Crast in irc.freenode.net:#django...

# 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 its 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() # Python 2.4
dispatcher = SimpleXMLRPCDispatcher(allow_none=False, encoding=None) # Python 2.5

 

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.
        """

        if len(request.POST):
                response = HttpResponse(mimetype="application/xml")
                response.write(dispatcher._marshaled_dispatch(request.raw_post_data))
        else:
                response = HttpResponse()
                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>')

        response['Content-length'] = str(len(response.content))
        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')

add the following to urls.py

urlpatterns = patterns('',
    (r'^xml_rpc_srv$', 'your_path.rpc_handler'),
)

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( int(sys.argv[1]), int(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, eliminates 'out of order' argument issues and it makes the code more self-documenting).

Have fun!

  • Brendan W. McAdams

I wrote up a modified version of the XML-RPC view that uses a template for documentation. -- Adam Blinkinsop (Link is no longer valid. Author any chance for update it?)


I've taken the basics of the SimpleXMLRPCDispatcher above and have turned it into a distributable Django app, django_xmlrpc. -- Graham Binns


I've wrote pingback implementation on top of this XML-RPC dispatcher. --Alexander Solovyov


Testing your XML-RPC views using the Django test client

I wrote up a small how-to on how to test your XML-RPC views using the Django test client as an XML-RPC transport: http://www.technobabble.dk/2008/apr/02/xml-rpc-dispatching-through-django-test-client/

-- Christian Joergensen


Using the SimpleXMLRPCDispatcher above and integrating it with a JSONRPCDispatcher, I created a Django application that can handle both XMLRPC and JSONRPC requests. It uses a customizable Django template for self-documentation.


If you see error 403, just add decorator:

  • from django.views.decorators.csrf import csrf_exempt
  • ...
  • @csrf_exempt
  • def rpc_handler ...
Last modified 3 years ago Last modified on 06/14/11 02:32:19