1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 | # soaplib_handler.py
from soaplib.wsgi_soap import SimpleWSGISoapApp
from soaplib.service import soapmethod
from soaplib.serializers import primitive as soap_types
from django.http import HttpResponse
class DjangoSoapApp(SimpleWSGISoapApp):
def __call__(self, request):
django_response = HttpResponse()
def start_response(status, headers):
status, reason = status.split(' ', 1)
django_response.status_code = int(status)
for header, value in headers:
django_response[header] = value
response = super(SimpleWSGISoapApp, self).__call__(request.META, start_response)
django_response.content = "\n".join(response)
return django_response
# views.py - sample view
from soaplib_handler import DjangoSoapApp, soapmethod, soap_types
class HelloWorldService(DjangoSoapApp):
__tns__ = 'http://my.namespace.org/soap/'
@soapmethod(soap_types.String, soap_types.Integer, _returns=soap_types.Array(soap_types.String))
def say_hello(self, name, times):
results = []
for i in range(0, times):
results.append('Hello, %s'%name)
return results
hello_world_service = HelloWorldService()
# urls.py
urlpatterns = patterns(
'',
(r'^hello_world/', 'foo.views.hello_world_service'),
(r'^hello_world/service.wsdl', 'foo.views.hello_world_service'),
)
|
Comments
This is a great example. Thanks!
#
This doesn't work for me because of problems with wsgi.input - have you actually successfully run this? The server just hangs for me trying to read the request from the client. I really wish it would work cause it's such a simple way of structuring this and soaplib looked pretty nice.
#
I've just started to use this (it works). I have 2 comments:
When you use super() you usually pass the class you are in (not the base class).
To automatically follow Django model relationships I have written a little
SoapDjangoArraytype; which will follow a reverse foreign key or m2m relationship:class SoapDjangoArray(soap_types.Array):#
If you are having a problem with wsgi input, you may want to ensure your webserver is correctly serving WSGI. If you're using apache, you can follow the guide here to set up mod_wsgi: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
I had a problem with it hanging as well, but I didn't have mod_wsgi set up correctly. This fixed the issue.
I'm having another issue though, from inside soaplib if I try to 'say_hello': File "/usr/lib/python2.5/site-packages/soaplib/soap.py", line 129, in from_soap if len(body.getchildren()): AttributeError: 'NoneType' object has no attribute 'getchildren'
#
In reference to my last post : this was a user error. I had set up my client as http://localhost:8000/hello_world/service.wsdl instead of http://localhost:8000/hello_world/. Works as intended now.
#
You guys are so close!
Ok, so the way I see it is that manage.py (calling manage.py runserver) is setup by default to execute the command (in /usr/lib/python/site-packages/django/core/management/commands) depending on your install runserver.py which seems to me is written with the RESTful pattern in mind. Here is a tutorial that describes how to write a custom command:
http://oebfare.com/blog/2008/nov/03/writing-custom-management-command/
Note that this tutorial demonstrates some interesting ways to use the WSGIServer provided by CherryPy.
Seeing as how we're working with SOAP, it would stand to reason to follow this pattern by implementing a new command and going from there. Could even go so far as to implement a command that supports both the CherryPy WSGI and the soaplib WSGI.
Personally I intend to write my own which initially I only care to have support for the soaplib wsgi but also the ability to allow each SOAP project app its ability to have a sudo-static instance or an instance of an object that remains intact so long as manage.py runsoapserver is running. Since this is the server instance.
Something I haven't thought of yet is whether or not the Django.core.handler.wsgihandler will suffice for use with the soaplib wsgi server. it would stand to reason that since I need to get a "sudo-static" instance of an object that remains as such so long as the WSGI server is running that I'll need to get that object to the appropriate views somehow. Not to mention the handler's filename is "wsgi.py" which kinda pushes anything I might want to write that's "wsgi" out of the way assuming I can't do that, any thoughts or suggestions to this approach I've come up with would be awesome!
Since requests are handled this way, "sudo-static" object instances would be pretty easy to conceal from views that they don't belong to. The idea being, the server gets a request, decides what app is being called on, then passes the instance that belongs to it. Some uses for this would be a way to have something like for example a thread pool that I can have control over via a SOAP API... something that runs while I'm away :)
... again any thoughts are welcome
#
@csar: I'm having the same problem. Do you have a solution yet?
#
Got it: change soaplib_handler into:
soaplib_handler.py
from soaplib.wsgi_soap import SimpleWSGISoapApp from soaplib.service import soapmethod from soaplib.serializers import primitive as soap_types import StringIO
from django.http import HttpResponse
class DumbStringIO(StringIO.StringIO): def read(self, n): return self.getvalue()
class DjangoSoapApp(SimpleWSGISoapApp):
#
It also hangs for me also,
emilianoheyns's patch works fine.
Thanks
#
The snippet works very well, the only problem I have is that the reply has no namespace defined :S
#
There is a bug in soaplib v8.1 The generated wsdl contains an error.
see: http://github.com/jkp/soaplib/issues/#issue/12
soapui & axis clients don't accept this wsdl
#