Version 27 (modified by 17 years ago) ( diff ) | ,
---|
rubber%252Brain%252Bboot%252B%252B%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Frubber%25252Drain%25252Dboot.html%252B%25255Drubber%252Brain%252Bboot%25255B%25252FURL%25255D%252B%252B%252B%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Frubber%25252Drain%25252Dboot.html%252B%25253Erubber%252Brain%252Bboot%25253C%25252Fa%25253E%252B%252B%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Frubber%25252Drain%25252Dboot.html%252Brubber%252Brain%252Bboot%252B%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwomens%25252Drain%25252Dboot.html%252B%25253Ewomens%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fkid%25252Drain%25252Dboot.html%252B%25253Ekid%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwoman%25252Drain%25252Dboot.html%252B%25253Ewoman%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fkid%25252Drain%25252Dboot.html%252B%25255Dkid%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fchild%25252Drain%25252Dboot.html%252B%25253Echild%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Findex.html%252B%25255Drain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Frubber%25252Drain%25252Dboot.html%252B%25255Drubber%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fchild%25252Drain%25252Dboot.html%252B%25255Dchild%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fgucci%25252Drain%25252Dboot.html%252B%25253Egucci%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Findex.html%252B%25253Erain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwomens%25252Drubber%25252Drain%25252Dboot.html%252B%25255Dwomens%252Brubber%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwomens%25252Drain%25252Dboot.html%252B%25255Dwomens%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fburberry%25252Drain%25252Dboot.html%252B%25255Dburberry%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Frubber%25252Drain%25252Dboot.html%252B%25253Erubber%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fcoach%25252Drain%25252Dboot.html%252B%25253Ecoach%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fcoach%25252Drain%25252Dboot.html%252B%25255Dcoach%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwoman%25252Drain%25252Dboot.html%252B%25255Dwoman%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25255BURL%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fgucci%25252Drain%25252Dboot.html%252B%25255Dgucci%252Brain%252Bboot%25255B%25252FURL%25255D%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fburberry%25252Drain%25252Dboot.html%252B%25253Eburberry%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A%25253Ca%252Bhref%25253D%252Bhttp%25253A%25252F%25252Fgeocities.com%25252Fshoeshere%25252Frain%25252Dboots%25252Fwomens%25252Drubber%25252Drain%25252Dboot.html%252B%25253Ewomens%252Brubber%252Brain%252Bboot%25253C%25252Fa%25253E%25250D%25250A3= XML-RPC =
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 added 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 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. """ 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>') 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')
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
I've taken the basics of the SimpleXMLRPCDispatcher above and have turned it into a distributable Django app, django_xmlrpc. -- Graham Binns