Suds массив массивов не вложенных

Позвольте мне предварить это, сказав, что я все еще довольно новичок в SOAP и в том, как все должно работать. Я работаю с API вертикального ответа.

У меня возникли проблемы с получением suds для правильного построения xml для запроса. Вот код:

from suds.client import Client

url = 'https://api.verticalresponse.com/wsdl/1.0/VRAPI.wsdl'
client = Client(url)
vr = client.service
...
test_list = (
    (
        {
            'name' : 'email_address',
            'value' : login['username'],
        },
        {
            'name' : 'First_Name',
            'value' : 'VR_User',
        }
    ),
    (
        {
            'name' : 'email_address',
            'value' : '[email protected]',
        },
        {
            'name' : 'First_Name',
            'value' : login['username'],
        },
    ),
)

# sid and cid are correctly retrieved prior to this point
print "Sending test message..."
vr.sendEmailCampaignTest({
    'session_id' : sid,
    'campaign_id' : cid,
    'recipients' : test_list,
})

В этом контексте login['username'] — это просто адрес электронной почты.

Этот код вызывает эту ошибку:

suds.WebFault: Server raised fault: 'Application failed during request deserialization: Too many elements in array. 4 instead of claimed 2 (2)

Вот определение sendEmailCampaignTest: http://developers.verticalresponse.com/api/soap/methods/campaigns/sendemailcampaigntest/

Вот xml, который выводит журнал. Этот XML неверен и не работает (я удалил session_id и list_id для отображения здесь):

<?xml version="1.0" encoding="utf-8" ?>
DEBUG:suds.client:headers = {'SOAPAction': u'"VR/API/1_0#sendEmailCampaignTest"', 'Content-Type': 'text/xml; charset=utf-8'}
ERROR:suds.client:<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns3="http://api.verticalresponse.com/1.0/VRAPI.xsd" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns4="VR/API/1_0" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns0:Body>
      <ns4:sendEmailCampaignTest>
         <args xsi:type="ns3:sendEmailCampaignTestArgs">
            <session_id xsi:type="ns1:string">redacted</session_id>
            <campaign_id xsi:type="ns1:int">redacted</campaign_id>
            <recipients xsi:type="ns3:ArrayOfNVDictionary" ns2:arrayType="ns3:NVDictionary[2]">
               <item>
                  <name xsi:type="ns1:string">email_address</name>
                  <value xsi:type="ns1:string">[email protected]</value>
               </item>
               <item>
                  <name xsi:type="ns1:string">First_Name</name>
                  <value xsi:type="ns1:string">VR_User</value>
               </item>
               <item>
                  <name xsi:type="ns1:string">email_address</name>
                  <value xsi:type="ns1:string">[email protected]</value>
               </item>
               <item>
                  <name xsi:type="ns1:string">First_Name</name>
                  <value xsi:type="ns1:string">[email protected]</value>
               </item>
            </recipients>
         </args>
      </ns4:sendEmailCampaignTest>
   </ns0:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:http failed:
<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Client</faultcode><faultstring>Application failed during request deserialization: Too many elements in array. 4 instead of claimed 2 (2)
</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

Я переношу свой скрипт на основе следующего ruby-скрипта (предоставленного компанией Vertical Response):

test_list = [
           [{
              'name' => 'email_address',
              'value' => $username
            },
            {
              'name' => 'First_Name',
              'value' => 'VR_User'
            }
           ],
           [{
              'name' => 'email_address',
              'value' => '[email protected]'
            },
            {
              'name' => 'First_Name',
              'value' => $username
            }
           ]
          ]
print "Sending test message...\n"
temp0 = vr.sendEmailCampaignTest({
                                 'session_id' => sid,
                                 'campaign_id' => cid,
                                 'recipients' => test_list,
                               })

Он выводит следующий xml. Этот XML правильный и работает (я удалил session_id и list_id):

<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <env:Body>
    <n1:sendEmailCampaignTest xmlns:n1="VR/API/1_0"
        env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <args xmlns:n2="http://api.verticalresponse.com/1.0/VRAPI.xsd"
          xsi:type="n2:sendEmailCampaignTestArgs">
        <session_id xsi:type="xsd:string">redacted</session_id>
        <campaign_id xsi:type="xsd:int">redacted</campaign_id>
        <recipients xmlns:n3="http://schemas.xmlsoap.org/soap/encoding/"
            xsi:type="n3:Array"
            n3:arrayType="n2:NVDictionary[2]">
          <item xsi:type="n3:Array"
              n3:arrayType="n2:NVPair[2]">
            <item>
              <name xsi:type="xsd:string">email_address</name>
              <value href="#id9496430"></value>
            </item>
            <item>
              <name xsi:type="xsd:string">First_Name</name>
              <value xsi:type="xsd:string">VR_User</value>
            </item>
          </item>
          <item xsi:type="n3:Array"
              n3:arrayType="n2:NVPair[2]">
            <item>
              <name xsi:type="xsd:string">email_address</name>
              <value xsi:type="xsd:string">[email protected]</value>
            </item>
            <item>
              <name xsi:type="xsd:string">First_Name</name>
              <value href="#id9496430"></value>
            </item>
          </item>
        </recipients>
      </args>
    </n1:sendEmailCampaignTest>
    <value id="id9496430"
        xsi:type="xsd:string"
        env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">[email protected]</value>
  </env:Body>
</env:Envelope>

Я так понимаю, что ошибка в построении получателей. Он должен содержать два элемента, каждый из которых содержит два элемента, но мой скрипт Python, использующий suds, настраивает его так, чтобы он содержал четыре невложенных элемента. Итак, мой вопрос: как я могу заставить suds правильно построить xml?

редактировать: что я пробовал:

>>> url = 'https://api.verticalresponse.com/wsdl/1.0/VRAPI.wsdl'
>>> client = Client(url)
>>> args = client.factory.create('ns0:sendEmailCampaignTestArgs')  
>>> args
(sendEmailCampaignTestArgs){
   session_id = None
   campaign_id = None
   recipients = 
      (ArrayOfNVDictionary){
         _arrayType = ""
         _offset = ""
         _id = ""
         _href = ""
         _arrayType = ""
      }
 }

Мне кажется, что ArrayOfNVDictionary неправильно строится с помощью suds (у него нет фактического элемента массива, который мог бы содержать NVDictionary), любая помощь в расчете того, что вы были бы великолепны.


person joshcartme    schedule 06.04.2012    source источник


Ответы (1)


Весь смысл SOAP в том, что вызовы удаленных методов и аргументы должны выглядеть как собственные методы и объекты выбранного вами языка.

Чтобы избежать ошибок, всегда используйте определенные типы SOAP, как показано в этом (непроверенном) фрагменте кода:

>>> recipient_list = [ 
...     ('[email protected]', 'Enoch'), 
...     ('[email protected]', 'Bill'), 
... ]
>>> client = suds.client.Client('https://api.verticalresponse.com/wsdl/1.0/VRAPI.wsdl')
>>> args = client.factory.create('ns0:sendEmailCampaignTestArgs')
>>> for email, first_name in recipient_list:
...     recipient = client.factory.create('ns0:NVDictionary')
...     recipient['email_address'] = email
...     recipient['First_Name'] = first_name
...     args.recipients.append(nvdict)
>>> args.session_id = sid
>>> args.campaign_id = cid
>>> client.service.sendEmailCampaignTest(args)

ИМХО, явный код, подобный приведенному выше, чище и проще в обслуживании.

Конечно, вы можете проигнорировать мой совет, в этом случае я думаю, что test_list должен выглядеть так:

test_list = [ 
    { 
        'email_address': '[email protected]', 
        'First_Name': 'Josh' },
    },
    { 
        'email_address': '[email protected]', 
        'First_Name': 'Josh' },
    },
]
person Paulo Scardine    schedule 06.04.2012
comment
Итак, когда я пытаюсь что-то подобное, это дает мне: AttributeError: экземпляр ArrayOfNVDictionary не имеет атрибута «добавлять» (я также изменил его на args.recipients.append(recipient), а не на append(nvdict). У вас есть какие-либо идеи по этому поводу? ? - person joshcartme; 07.04.2012
comment
@joshcartme: в идеальном мире args.recipients должен выглядеть как массив, но SOAP - очень запутанный стандарт, иногда suds не понимают некоторые WSDL. Попробуйте args.recipients = [] перед циклом. - person Paulo Scardine; 07.04.2012
comment
Хм, когда я помещаю args.recipients = [], это дает мне следующую ошибку: suds.WebFault: Ошибка сервера: «Не ссылка на МАССИВ. Я также попробовал другое ваше предложение по созданию test_list, и оно выдало ту же ошибку. Спасибо за помощь. - person joshcartme; 07.04.2012
comment
@joshcartme: глядя на запрос, сгенерированный ruby, я бы попробовал список списков client.factory.create('ns0:NVPair') - person Paulo Scardine; 07.04.2012
comment
Кажется, я тоже пробовал NVPair, но это тоже не сработало. Вы, вероятно, могли бы использовать WSDL и создать случайный cid (числовой) и sid (буквенно-цифровой). На самом деле это, конечно, не сработает, но вы можете проверить синтаксис. Я в растерянности, в понедельник опять заберу. Спасибо за помощь. - person joshcartme; 07.04.2012
comment
Я предполагаю, что suds плохо справляется с этим WSDL - возможно, версия SOAP не поддерживается. Я перешел с verticaresponse на mailchimp, поэтому у меня больше нет учетной записи для тестирования. Кстати, API mailchimp основан на JSON, и есть пара хороших модулей для взаимодействия. - person Paulo Scardine; 07.04.2012
comment
Я искал mailchimp, но клиент, с которым я работаю, является некоммерческим, поэтому цены на вертикальные ответы намного лучше. Вероятно, вы могли бы протестировать WSDL с поддельными cid и sid, чтобы получить правильный синтаксис, потому что ошибка возникает до отправки запроса, я полагаю. Тогда, если это было правильно, он, вероятно, вернул бы, что cid/sid были неправильными или что-то в этом роде. Вы также можете создать бесплатную учетную запись в вертикальном ответе, а затем попросить разрешить доступ к API здесь: developers .verticalresponse.com/api-request-form, но я полностью понимаю, если вы не хотите этого делать. Спасибо! - person joshcartme; 07.04.2012
comment
Я отредактировал конец своего вопроса тем, что пробовал, согласны ли вы с тем, что результат, который мне дали, выглядит неверным? - person joshcartme; 10.04.2012
comment
@joshcartme: WSDL содержит имена типов с [], может ли это быть проблемой? - person Paulo Scardine; 10.04.2012
comment
Я разговаривал с сопровождающим suds и, по-видимому, столкнулся с ошибкой в ​​suds. На самом деле он рекомендовал мне всегда использовать структуры Python с suds, а не использовать client.factory.create. Я обновлю вопрос, если разберусь. - person joshcartme; 12.04.2012
comment
@joshcartme: позор мне, прямо противоположное тому, что я тебе говорил. - person Paulo Scardine; 13.04.2012
comment
не беспокойтесь, то, что вы сказали, имело смысл, но я думаю, что suds лучше поддерживает структуры python, чем использование client.factory.create() - person joshcartme; 13.04.2012