#python #suds
#python #suds
Вопрос:
У меня есть сервер WSDL с некоторыми методами, каждый из которых принимает DataModelType. Ранее я использовал это таким образом:
import suds.transport.http
from suds.client import Client
trans = suds.transport.http.HttpAuthenticated(username=username,
password=password)
__client = Client(url, transport=trans)
func = __client.service.__getattr__("ReceiveData")
argument = __client.factory.create('DataModelType')
argument["Key"] = "0001"
return func(argument)
И это отлично сработало.
Он автоматически создал XML с помощью DataRequest:
<Envelope>
<Body>
<DataRequest>
<DataModelType>
<Key>0001</Key>
<Data></Data>
</DataModelType>
</DataRequest>
</Body>
</Envelope>
Отправил его, и в качестве ответа я получил что-то вроде:
<Envelope>
<Body>
<DataResponse>
<DataModelType>
<Key>0001</Key>
<Data>"Help me solve that magic, please"</Data>
</DataModelType>
</DataResponse>
</Body>
</Envelope>
И return func(аргумент) вернул мне объект python, построенный из DataModelType
Теперь я обнаружил, что у тега DataRequest есть параметры, которые я должен установить для сервера, чтобы получить правильный ответ. Но как мне установить для них pythonic throw suds, не извлекая XML, анализируя его, а затем отправляя его по HTTP-транспорту?
Если отправка по http-транспорту — это только один из способов, как это сделать? Я пытаюсь смоделировать то, что происходит внутри return func(аргумент), но даже если он принимает точно такие же параметры, результат будет другим.
Есть ли в suds интерфейс для установки свойств convert, о которых он заботится сам? Как решить эту задачу?
Ответ №1:
Я решил это. Вместо примера, о котором шла речь, нам нужно сделать использование функции более конкретным.
import suds.transport.http
from suds.client import Client
trans = suds.transport.http.HttpAuthenticated(username=username,
password=password)
__client = Client(url, transport=trans)
func = __client.service.__getattr__("ReceiveData")
argument = __client.factory.create('DataModelType')
argument["Key"] = "0001"
#getting internal soap class and extracting entire soap_object:
clientclass = func.clientclass({})
SoapClient = clientclass(func.client, func.method)
binding = func.method.binding.input
soap_xml = binding.get_message(func.method, [modelthings], {})
#fix anything what we want, that is representation of all envelope that should be sent
soap_xml.children[0].children[1].children[0].attributes.append(u'attachmentInfo="true"')
soap_xml.children[0].children[1].children[0].attributes.append(u'attachmentData="true"')
soap_xml.children[0].children[1].children[0].attributes.append(u'ignoreEmptyElements="true"')
#then prepare it as suds would do it:
SoapClient.last_sent(soap_xml)
plugins = PluginContainer(SoapClient.options.plugins)
plugins.message.marshalled(envelope=soap_xml.root())
if SoapClient.options.prettyxml:
soap_xml = soap_xml.str()
else:
soap_xml = soap_xml.plain()
soap_xml = soap_xml.encode('utf-8')
plugins.message.sending(envelope=soap_xml)
request = Request(SoapClient.location(), soap_xml)
request.headers = SoapClient.headers()
my_reply = SoapClient.options.transport.send(request)
ctx = plugins.message.received(reply=my_reply)
my_reply = ctx.reply
if SoapClient.options.retxml:
answer = my_reply
else:
answer = SoapClient.succeeded(binding, my_reply)
return answer
Итак, мы по-прежнему используем suds как можно больше, но получаем доступ к любому полю всего сообщения SOAP.