Posting in the Magento forums has been disabled pending the implementation of a new and improved forum solution which should better serve the community.

For new questions please post at magento.stackexchange.com, the community-run support site for the Magento community. We will be providing updates on the new forum solution soon. For questions or concerns please email community@magento.com.

Magento Forum

[SOLVED] Core API confusion
 
Chris Farley
Member
 
Total Posts:  43
Joined:  2008-03-09
 

I’m connecting to Magento via XML-RPC using python.

I’ve no problem pulling the complete sales order list with this little program:

from xmlrpclib import *
server Server('http://127.0.0.1/magento/api/xmlrpc/')
session server.login('user','password')
orderlist server.call(session'sales_order.list')
for 
x in orderlist:
   print 
"%s %s %s %s" % (x["increment_id"],x["billing_name"]x["status"]x["grand_total"])

However, once I start trying to add filters, I get an exception. Magento doesn’t throw an xmlrpc fault; instead it craps out and sends an html error page. Here’s code that causes the error:

filters ["billing_name",["like","&#xMi;ke%"]]
filtered_list 
server.call(session'sales_order.list'[filters])

The html response says:

Fatal error.
Call to a member function getAttributeCode() on a non-object in /var/www/magento/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php on line 229

I’m using Magento 1.1.6

Hopefully I’m just doing something wrong! Thanks if you can help!

 
Magento Community Magento Community
Magento Community
Magento Community
 
Chris Farley
Member
 
Total Posts:  43
Joined:  2008-03-09
 

I rewrote my little python program so that it uses SOAP. Unlike XML-RPC, I get a proper SOAP fault. The fault is:

SOAPpy.Types.faultType: <Fault SOAP-ENV:Server: Call to a member function getAttributeCode() on a non-object>

I’m trying to figure out if I’m simply doing the filters wrong, or if this is some kind of Magento bug, or a problem with my Magento configuration, or an incompatibility between python’s soap/xmlrpc and php’s.

Here’s my SOAP program:

from SOAPpy import *
server SOAPProxy('http://localhost/magento/api/soap/?wsdl')
session server.login('user','password')

##### This next call is successful ######
order_list server.call(session'sales_order.list')
print 
"I found %d orders" len(order_list)

filters ["billing_name",["like","&#xMi;ke%"]]
##### This next call fails ######
filtered_orders server.call(session'sales_order.list'[filters])
print 
"I found %d orders" len(filtered_orders)

And here’s the complete output of my program:

I found 13 orders
<Fault SOAP-ENV:ServerCall to a member function getAttributeCode() on a non-object>
Traceback (most recent call last):
  
File "soap-magento.py"line 11in ?
    
filtered_orders server.call(session'sales_order.list'[filters])
  
File "/opt/local/lib/python2.4/site-packages/SOAPpy/Client.py"line 421in __call__
    
return self.__r_call(*args, **kw)
  
File "/opt/local/lib/python2.4/site-packages/SOAPpy/Client.py"line 443in __r_call
    self
.__hdself.__ma)
  
File "/opt/local/lib/python2.4/site-packages/SOAPpy/Client.py"line 357in __call
    raise p
SOAPpy
.Types.faultType: <Fault SOAP-ENV:ServerCall to a member function getAttributeCode() on a non-object>
 
Magento Community Magento Community
Magento Community
Magento Community
 
LeeSaferite
Guru
 
Avatar
Total Posts:  322
Joined:  2007-08-31
Lake City, FL
 

Dumb question, before I look at the code involved, did you try this with ‘billing_firstname’ and ‘billing_lastname’ ?  I know that ‘billing_name’ is not a real attribute, just a synthetic one used for display.

EDIT: Yes, I have read the examples given that use ‘billing_name’, I just don’t always trust the examples.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Chris Farley
Member
 
Total Posts:  43
Joined:  2008-03-09
 

Lee,

Yes, I tried filtering on other attributes. No difference. What I *really* want to do is to filter on status, but I’m using billing_name because it appears in those examples.

I think the problem is mapping the python arrays to soap. I ran the php example, and guess what? It works!

So I’ve been looking at the SOAP messages that are being sent to magento, particularly how the arrays are being mapped into soap.

PHP does this:

<SOAP-ENV:Body>
   <
ns1:call>
      <
sessionId.xsl:type="xsd:string">41bd21228379ed0bb86ad9a7013c97ad</sessionId>
      <
resourcePath.xsi:type="xsd:string">sales_order.list</resourcePath>
      <
args.SOAP-ENC:arrayType="ns2:Map[1]" xsi:type="SOAP-ENC:Array">
         <
item.xsi:type="ns2:Map">
            <
item>
               <
key.xsi:type="xsd:string">billing_name</key>
               <
value.xsi:type="ns2:Map">
                  <
item>
                     <
key.xsi:type="xsd:string">like</key>
                     <
value.xsi:type="xsd:string">&#xMi;ke%</value>
                  
</item>
               </
value>
            </
item>
         </
item>
      </
args>
   </
ns1:call>
</
SOAP-ENV:Body>

My python program is doing this:

<SOAP-ENV:Body>
   <
call SOAP-ENC:root="1">
      <
v1 xsi:type="xsd:string">079ecc15df1ae02d7186ea8805d21215</v1>
      <
v2 xsi:type="xsd:string">sales_order.list</v2>
      <
v3 SOAP-ENC:arrayType="xsd:list[1]" xsi:type="SOAP-ENC:Array">
         <
item SOAP-ENC:arrayType="xsd:ur-type[2]" xsi:type="SOAP-ENC:Array">
            <
item xsi:type="xsd:string">billing_name</item>
            <
item SOAP-ENC:arrayType="xsd:string[2]" xsi:type="SOAP-ENC:Array">
               <
item>like</item>
               <
item>&#xMi;ke%</item>
            
</item>
         </
item>
      </
v3>
   </
call>
</
SOAP-ENV:Body>

Obviously there are some syntax differences, but I think the important one is that my python arrays are being mapped to a list, and magento is expecting a map. I’m trying to experiment and find out what python concept maps to a map, but so far, haven’t found it.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Chris Farley
Member
 
Total Posts:  43
Joined:  2008-03-09
 

Half solved now!

I can’t figure out SOAP, but I have managed to get filters working in python using XML-RPC.

The call needs to look like this:

pending_orders = server.call(session, ‘sales_order.list’, [{"status”:{"=”:"pending"}}])

I need to use python dictionaries, and not arrays.

I still can’t make it work with SOAP, as the dictionaries map to SOAP structs, not SOAP maps. Whatever. I wanted to use XML-RPC anyway!

 
Magento Community Magento Community
Magento Community
Magento Community
 
rossigee
Jr. Member
 
Total Posts:  7
Joined:  2009-04-26
 

I also ran into this SOAPpy/MPHP SOAP issue…

http://www.magentocommerce.com/boards/viewthread/43635/

Nearly got a fix by creating a custom SOAPpy.Types.anyType subclass and using that for capturing/marshalling the missing ‘Map’. Will post a working test case on that thread when it works.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Pod1
Member
 
Avatar
Total Posts:  34
Joined:  2008-12-05
London///New York///Cape Town
 

I’ve pulled some example code together that shows how to use XMLRPC with the Magento API. You can browse it, and update it if you like, at http://code.google.com/p/python-magento/

Maybe, if there’s sufficient interest, we might get some re-usable Magento classes together in Python.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Ben Fitzhardinge
Jr. Member
 
Avatar
Total Posts:  29
Joined:  2010-03-25
 

i’ve been independently working on a magento-python API tool.
i’ve managed to get a fair few things done, but they are all within the scope of the project i am currently working on.
i wish you had posted this message a few months ago, i felt pretty damn lonely when i started working on magneto and python.

i’d be more than happy to give any of my work to the python-magento project.

 
Magento Community Magento Community
Magento Community
Magento Community
 
jeff_sov
Jr. Member
 
Total Posts:  8
Joined:  2009-12-31
 

Just found this post and your code on google.  Any thoughts on expanding to category/attributes?  I’d love to help expand the functionality if you want some.

 
Magento Community Magento Community
Magento Community
Magento Community
 
Ben Fitzhardinge
Jr. Member
 
Avatar
Total Posts:  29
Joined:  2010-03-25
 

below is my codes for dealing with categories,
it is simple, because the work i’ve been doing is simple,
but hopefully it gives you a good start on where to go with python and magento.

def catlist(serversession):
    return 
server.call(session'category.tree')

def catcreate(serversessioncatnameparentcat):
    
"""create a category, with passed variables, return the new categories ID"""
    
#create dict for category details
    
catdetail dict({
        
'name':catname,
        
'description':'',
        
'meta_description':'',
        
'meta_keywords':'',
        
'default_sort_by':'name',
        
'available_sort_by':'name,price',
        
'is_active':1
    }
)
    return 
server.call(session'category.create'[parentcatcatdetail])
    
pass
 
Magento Community Magento Community
Magento Community
Magento Community
 
Ben Fitzhardinge
Jr. Member
 
Avatar
Total Posts:  29
Joined:  2010-03-25
 
jeff_sov - 12 June 2010 06:41 PM

Just found this post and your code on google.  Any thoughts on expanding to category/attributes?  I’d love to help expand the functionality if you want some.

sorry seems you were talking about product creation?

anyway, here’s a copy of the whole thing.

i’ve also got an image update script, but i am yet to move that over into my magento.py file.

#!/usr/bin/env python
# encoding: utf-8
"""
magento.py

list of magneto api call routines in python

contact ben@fitzhardinge.net

Created by Ben Fitzhardinge on 2009-10-22.
Copyright (c) 2009 All rights reserved.
"""

import sys
import os
import xmlrpclib

def apiserver
(address):
    
"""connect to server return server object"""
    
return xmlrpclib.Server(address)
    
pass

def apisession
(serverusernamepassword):
    
"""open an api session and return the string"""
    
return server.login(usernamepassword)
    
pass

def prodget
(serversessionsku):
    
"""get product matching an sku"""
    
prodinfo server.call(session'product.info'[sku])
    return 
prodinfo
    pass


def prodcreate
(serversessionprodskuprodnameprodshrtproddescprodpriceprodweight=0prodcats=[]prodtype='simple'prodsites=[1]prodstatus=1):
    
"""create a product using the api"""
    
# retrieve current set information
    
currset server.call(session'product_attribute_set.list')
    
currsetid currset[0].get('set_id')
    
# build the dict for the new product.
    
proddetail dict({
        
'name':prodname
        
'websites':prodsites
        
'short_description':prodshrt
        
'description':proddesc
        
'price':prodprice,
        
'weight':prodweight,
        
'categories':prodcats,
        
'status':prodstatus,
        
'tax_class_id':'2' #2 = taxable product... hard coded for australian GST need to fix this
    
})
    
#build the new product info.
    
newprod [prodtypecurrsetidprodskuproddetail]
    
#run the request
    
return server.call(session'product.create'newprod)
    
pass

def produpdate
(serversessionprodskuprodnameprodshrtproddescprodpriceprodweight=0prodcats=[]prodsites=[1]prodstatus=1):
    
"""update a product using the api"""
    
# retrieve current set information
    
currset server.call(session'product_attribute_set.list')
    
currsetid currset[0].get('set_id')
    
# build the dict for the new product.
    
proddetail dict({
        
'name':prodname
        
'websites':prodsites
        
'short_description':prodshrt
        
'description':proddesc
        
'price':prodprice,
        
'weight':prodweight,
        
'categories':prodcats,
        
'status':prodstatus,
        
'tax_class_id':'2' #2 = taxable product... hard coded for australian GST need to fix this
    
})
    
#build the product info.
    
updateprod [prodskuproddetail]
    
#run the request
    
return server.call(session'product.update'updateprod)
    
pass


def invget
(server,session,sku):
    
"""docstring for invget"""
    
invinfo server.call(session'product_stock.list'[sku])
    try:
        return 
invinfo[0]
    except
:
        return (
{'sku':sku'product_id':"Error"'is_in_stock':"Error"'qty'"Error"})
    
pass

def invupdate
(server,session,sku,qty):
    
"""docstring for invupdate"""
    
if qty 0:
        
instock 1
    
else:
        
instock 0
    result 
server.call(session'product_stock.update'[sku, ({'qty':qty,'is_in_stock':instock})])
    return 
result
    pass

def catlist
(serversession):
    return 
server.call(session'category.tree')

def catcreate(serversessioncatnameparentcat):
    
"""create a category, with passed variables, return the new categories ID"""
    
#create dict for category details
    
catdetail dict({
        
'name':catname,
        
'description':'',
        
'meta_description':'',
        
'meta_keywords':'',
        
'default_sort_by':'name',
        
'available_sort_by':'name,price',
        
'is_active':1
    }
)
    return 
server.call(session'category.create'[parentcatcatdetail])
    
pass


def skulist
(serversession):
    
"""returns a list of SKUs on the system"""
    
productlist server.call(session'product.list')
    
skulist []
    
for product in productlist:
        
skulist.append(product.get('sku'))
    return 
skulist
    pass

def proddel
(server,session,sku):
    
"""deletes the specified product"""
    
return server.call(session'product.delete'[sku])
    
pass

def proddellist
(server,session,skulist):
    
"""docstring for proddellist"""
    
return server.call(session'product.delete'skulist)
    
pass

def find
(inlistkeyvalue):
    
"""function will search the dictionaries in the inlist
    returning a dictionary that matches
    or None if there are none
    or raises an assertion if the data is corrupt    """
    
matches [X for X in inlist if key in X and value == X[key]]
    assert len
(matches)<=1"Found more than one match for key:%s value:%s"%(key,value)
    if 
len(matches):
        return 
matches[0]
    
else:
        print 
"Found no match for key:%s value:%s"%(key,value)
    return 
None

def findall
(inlistkeyvalue):
    
"""function will search the dictionaries in the inlist
    returning a list of dictionaries that matche"""
    
matches [X for X in inlist if key in X and value in X[key]]
    
if len(matches):
        return 
matches
    
else:
        print 
"Found no match for key:%s value:%s"%(key,value)
    return 
None
    pass

.....

 
Magento Community Magento Community
Magento Community
Magento Community
 
Ben Fitzhardinge
Jr. Member
 
Avatar
Total Posts:  29
Joined:  2010-03-25
 

the rest

def invoicecreate(serversessionorder_inc_id):
    
"""takes an orders increment_id and generates an invoice"""
    
return server.call(session'sales_order_invoice.create'[order_inc_id,[],'Invoice Created',True,True])
    
pass

def generatenewinvoices
(serversession):
    
"""generates all invoices for orders lacking invoices"""
    
invoices server.call(session'sales_order_invoice.list')
    
orders server.call(session'sales_order.list')
    
uninvoicedorders []
    newinvoices 
[]
    
#compile list of order ids
    
for order in orders:
        
uninvoicedorders.append(order.get('order_id'))
    
# print "orders=",uninvoicedorders
    #remove from list previously invoiced things
    
for invoice in invoices:
        
uninvoicedorders.remove(invoice.get('order_id'))
    
# print "uninvoicedorders=",uninvoicedorders
    
for uninvoiced in uninvoicedorders:
        
order find(orders'order_id'uninvoiced)
        
newinvoice invoicecreate(serversessionorder.get('increment_id'))
        
# print "new invoice id=",newinvoice
        
newinvoices.append(newinvoice)
    return 
newinvoices
    pass
 
Magento Community Magento Community
Magento Community
Magento Community
 
Ben Fitzhardinge
Jr. Member
 
Avatar
Total Posts:  29
Joined:  2010-03-25
 

Hi python + magneto people,

i was going to post the issues i was having with the magento api and python xmlrpclib and creating partly shipped shipping entries.
but i solved it.

i figured we should perhaps start a thread for Magento + Python + xmlrpclib issues, so i created a new one here.
since this thread is old and solved.

Magento, Python and xmlrpclib

 
Magento Community Magento Community
Magento Community
Magento Community
Magento Community
Magento Community
Back to top