読者です 読者をやめる 読者になる 読者になる

DjangoでSOAPウェブサービスを実装する

PythonSOAPを扱う場合、いくつかサードパーティモジュールがあるのだけど、久しぶりに調べてみたら、Spyneというのがそこそこ活発に開発されてるようだ。
spyne - RPC that doesn't break your back.
どうやら、 soaplib の開発を停止して rpclib というモジュールを開発し、その名前を変更したものがSpyneだそうだ。
SpyneはPythonでRPCを実装するためのツールキット。
SOAPJSONXMLYAML、MessagePackなどのインターフェースをクライアント側に提供し、サーバー側のやインターフェースはWSGIDjango、Pyramidなどに対応する。
Spyneはクライアント側の実装を持たないため、SOAPであればsudsなどのクライアントモジュールを別途使用する。
suds
試したバージョンは、Python 2.7、Django 1.6.1、spyne 2.10.9、suds 0.4、lxml 3.2.4

コード例

service.py

Spyneのチュートリアルより。
サービスの実装はServiceBaseクラスを継承してメソッドを実装する。
srpcデコレータまたはrpcデコレータで、入力パラメータの型と出力の型を指定する。
srpcデコレータを使うと、単純な関数呼び出しのようにスタティックメソッドで実装できる。コンテキストが必要な場合はrpcデコレータを使う。

from spyne.decorator import srpc
from spyne.service import ServiceBase
from spyne.model.primitive import Integer
from spyne.model.primitive import Unicode
from spyne.model.complex import Iterable
from spyne.application import Application
from spyne.protocol.soap import Soap11
from spyne.server.django import DjangoApplication


class HelloWorldService(ServiceBase):
    @srpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(name, times):
        """「Hello, name」をtimesの数だけ返す
        """
        for i in range(times):
            yield u'Hello, %s' % name


application = Application(
    [HelloWorldService],
    tns='foo.example.com',
    in_protocol=Soap11(),  # 入力プロトコルにSOAP 1.1を指定
    out_protocol=Soap11()  # 出力プロトコルにSOAP 1.1を指定
)

# hello_appはDjangoのビュー関数相当になる
hello_app = csrf_exempt(DjangoApplication(application))

実装したサービスは、Applicationクラスで入力プロトコルを指定してまとめる。
Djangoから使用する場合は、DjangoApplicationクラスでラップするとview関数相当になる。

urls.py
from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
    url(r'^foo_service/$', 'foo_service.service.hello_app'),
)

感想

SOAPの実装がシンプルにできた上にDjangoからも簡単に扱えるあたりがいい感じ。
一つサービスを実装すればSOAP以外のプロトコルにも対応できるあたりもうれしい。
SOAPのオーバーヘッドが気になるならMessagePackRPCを使ってみるのもよさそう。
サンプルコード全体はbitbucketに置いた。
tokibito / sample_nullpobug / source / django / webservice — Bitbucket