My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
RemoteCalls  
Various samples of code for remote calls to the tryton server
Phase-Support
Updated Mar 23, 2010 by cedkrier@gmail.com

Remote Calls

Each example shows two remote calls, the first one is the 'search' to get the first 10 party ids. The second one calls name_get on these ids, then outputs the result, which looks like: [(1, u'Supplier A'), (2, u'Supplier B'), (3, u'Customer A'), (4, u'Customer B')]

Note:

  • By default trytond only listens for NET-RPC calls on port 8070. To allow XML-RPC, you must activate it. This is done in the config file (which defaults to etc/trytond.conf but can be changed using the -c switch) containing at least:
# Activate the xml-rpc protocol
xmlrpc = True
# Configure the port for the xml-rpc protocol to listen
xmlport = 8069
  • NET-RPC is only available with Python since it uses pickle to serialize data. The data sent over the network are more compact than with XML-RPC, hence speeding up the requests.

Version 1.6

XML-RPC in Python

import xmlrpclib

PASSWORD = 'admin'
USER = "admin"

# Get user_id and session
s = xmlrpclib.ServerProxy ('http://%s:%s@localhost:8069/try' % (USER, PASSWORD))

# Get the user context
context = s.model.res.user.get_preferences(True, {})

# Print all methods (introspection)
print s.system.listMethods()

# Search parties and print rec_name
party_ids = s.model.party.party.search(
        [], # search clause
        0,  # offset
        10, # limit
        False, # order
        context)  # context

print s.model.party.party.read(
        party_ids, # party ids
        ['rec_name'], # list of fields
        context) # context

# Execute report
type, data, _ = s.report.party.label.execute(
        party_ids, # party ids
        {}, # data
        context) # context

Version 1.2, 1.4

XML-RPC in Python

import xmlrpclib

PASSWORD = 'admin'
USER = "admin"

# Get user_id and session
s = xmlrpclib.ServerProxy ('http://localhost:8069/try')
user_id, session = s.common.db.login(USER, PASSWORD)

# Get the user context
context = s.model.res.user.get_preferences(user_id, session, True, {})

# Print all methods (introspection)
print s.system.listMethods()

# Search parties and print rec_name
party_ids = s.model.party.party.search(user_id, session,
                                   [], # search clause
                                   0,  # offset
                                   10, # limit
                                   False, # order
                                   context)  # context

print s.model.party.party.read(user_id, session,
                             party_ids, # party ids
                             ['rec_name'], # list of fields
                             context) # context

# Execute report
type, data, _ = s.report.party.label.execute(user_id, session,
                             party_ids, # party ids
                             {}, # data
                             context) # context

NET-RPC in Python

from trytond import pysocket

PASSWORD = 'admin'
DB = "try"
USER = "admin"

sock = pysocket.PySocket()
sock.connect('127.0.0.1', '8070')

# Get user_id and session
sock.send((DB, USER, PASSWORD, 'common', 'db', 'login'))
user_id, session = sock.receive()

# Get the user context
sock.send((DB, user_id, session, 'model', 'res.user', 'get_preferences',
               True, {}))
context = sock.receive()

# Search parties and print rec_name
sock.send((DB, user_id, session, 'model', 'party.party', 'search',
               [],  # search clause
               0,   # offset
               10,  # limit
               False, # order
               {}))  # context

party_ids = sock.receive()

sock.send((DB, user_id, session, 'model', 'party.party', 'read',
               party_ids, # party ids
               ['rec_name'], # list of fields
               context)) #context
print sock.receive()

# Execute report
sock.send((DB, user_id, session, 'report', 'party.label', 'execute',
               party_ids, # party ids
               {}, # data
               context)) # context
type, data, _ = sock.receive()

# Logout, disconnect, cleanup
sock.send((DB, USER, PASSWORD, 'common', 'db', 'logout'))
_ = sock.receive()
sock.disconnect()
del sock

Version 1.0

XML-RPC in Python

import xmlrpclib

PASSWORD = 'admin'
DB = "try"
USER = "admin"

# Get user_id and session
common = xmlrpclib.ServerProxy ('http://localhost:8069/xmlrpc/common')
user_id, session = common.login(DB, USER, PASSWORD)

object = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/object')

party_ids = object.execute(DB, user_id, session, 'party.party', 'search',
                           [], # search clause
                           0,  # offset
                           10, # limit
                           {})  # context

print object.execute(DB, user_id, session, 'party.party', 'name_get',
                     party_ids)

XML-RPC in Ruby

require 'xmlrpc/client'
require 'pp'

PASSWORD = 'admin'
DB = "try"
USER = "admin"

# Get user_id and session
common = XMLRPC::Client.new2("http://localhost:8069/xmlrpc/common")
user_id, session = common.call('login', DB, USER, PASSWORD)

object = XMLRPC::Client.new2("http://localhost:8069/xmlrpc/object")

party_ids = object.call('execute', DB, user_id, session, 'party.party', 'search',
                        [],  # search clause
                        0,   # offset
                        10,  # limit
                        {})  # context
pp object.call('execute', DB, user_id, session,  'party.party', 'name_get',
               party_ids)

NET-RPC in Python

from trytond import pysocket

PASSWORD = 'admin'
DB = "try"
USER = "admin"

sock = pysocket.PySocket()
sock.connect('127.0.0.1', '8070')

# Get user_id and session
sock.send(('common', 'login', DB, USER, PASSWORD))
user_id, session = sock.receive()

sock.send(('object', 'execute', DB, user_id, session, 'party.party', 'search',
           [],  # search clause
           0,   # offset
           10,  # limit
           {}))  # context

party_ids = sock.receive()

sock.send(('object', 'execute', DB, user_id, session, 'party.party', 'name_get',
           party_ids))
print sock.receive()
Comment by rico.glo...@gmail.com, Mar 19, 2011

Ruby Example, validated to work with 1.8

# Prepare the Client
require 'pp
require 'xmlrpc/client'
obj = XMLRPC::Client.new2('http://USER:PASSWORD@localhost:8069/DATABASE')

# This will retrieve the Tree to show the Models you might later want to manipulate
pp obj.call('model.ir.ui.menu.search', ['OR', ['parent', '=', false]], 0, 5, FALSE, {})
#=> [60, 135, 74, 57, 1]
pp obj.call('model.ir.ui.menu.read', [1, 57, 74, 135, 60], {})
#=> { .., 'name' => 'Administration', 'id' => 1, 'childs' => [2, 14, 18, 23, 25, 36, 42, 47, 51, 59], .. }, { .. }

# User selects Menu Administration
pp obj.call('model.ir.ui.menu.search', ['OR', ['parent', '=', 1]], 0, 5, FALSE, {})
#=> [2, 14, 18, 23, 25]

pp obj.call('model.ir.ui.menu.read', [2,14,18,23,25], {})
# => { .. } containing Objects like "User Interface, Models, Scheduler" as shown in the UI Tree

# now id 23 is the Scheduler here, it has childs => [24]
pp obj.call('model.ir.ui.menu.read', [24], {})
# =>  [{ .., "action"=>"ir.action.act_window,21", .. }] 
# so we have an action linked, its actually doing something

# Lets find out to what model that actionWindow is linked:
pp obj.call('model.ir.action.act_window.read', [21], {})
#=> [{"name"=>"Scheduled Actions", ..,   "res_model"=>"ir.cron"}]

# And now let us retrieve the Objects that are linked:
pp obj.call('model.ir.cron.search', [], 0, 10, {})
#=> [1]

pp obj.call('model.ir.cron.read', [1], {})
#=> [{"model"=>"ir.trigger", ..}]

Congratulations, at this point you have retrieved your first object off the Database.

Comment by rico.glo...@gmail.com, Mar 19, 2011

notes:

  • all obj.call() return an array, thats sometimes not correctly shown in the example
  • the call for model.ir.ui.menu.search with 'parent = 1' is superflouos, since its a duplicate information to the childs Array in the previous call
  • the very same call limits its output to 5 (returning elements 0 .. 5), thus it does not contain the same information as the previous call (which is not limited)
Comment by rico.glo...@gmail.com, Mar 19, 2011

Also for those interested in the real RPC, because they dont have a real XML-RPC API handy:

# Query
POST /tryton HTTP/1.0
Accept: */*
Connection: keep-alive
User-Agent: XMLRPC::Client (Ruby 1.8.7)
Content-Type: text/xml; charset=utf-8..Authorization: Basic YWRtaW46ZGEyMW5pbg==
Content-Length: 523
Host: localhost:8069 (CrLfCrLf)

<?xml version="1.0" ?>
 <methodCall> 
   <methodName>model.ir.ui.menu.search</methodName>
   <params>
<!-- search clause starts here -->
    <param>
     <value> 
      <array> <data>
        <value><string>OR</string></value>
        <value>
         <array><data>
          <value>string>parent</string></value>
          <value><string>=</string></value>
          <value><boolean>0</boolean></value>
         </data></array>
        </value></data>
      </array>
     </value>
    </param>
<!-- search clause ends here -->
    <param><value><i4>0</i4></value></param> <!-- offset -->
    <param><value><i4>5</i4></value></param> <!-- limit -->
    <param><value><boolean>0</boolean></value></param> <!-- order -->
    <param><value><struct/></value></param> <!-- context -->
 </params>
</methodCall>


# Result:
HTTP/1.0 200 OK
Server: BaseHTTP/0.3 Python/2.6.6
Date: Sat, 19 Mar 2011 21:33:46 GMT
Content-type: text/xml
Content-length: 283

<?xml version='1.0'?>
<methodResponse>
 <params>
  <param><value><array><data>
     <value><int>60</int>/value>
     <value><int>135</int></value>
     <value><int>74</int></value>
     <value><int>57</int></value>
     <value><int>1</int></value>
   </data></array></value>
  </param>
 </params>
</methodResponse>.

# similarily, a more complex answer might look like this: (data omitted)
<?xml version="1.0" ?>
 <methodResponse>
  <params>
   <param><value><array><data>
       <value><struct>
         <member>
          <name>function</name>
          <value><string>trigger_time</string></value>
         </member>
         <member>
          <name>create_uid</name>
          <value><int>0</int></value>
         </member>
         <member>
          <name>request_user</name>
          <value><int>1</int></value>
         </member>
         <member>
          <name>create_date</name>
          <value><dateTime.iso8601>20110316T20:38:49</dateTime.iso8601></value>
         </member>
         <member>
          <name>args</name>
          <value><boolean>0</boolean></value>
         </member>
         <member>
          <name>companies</name>
          <value><array>
           <data></data>
          </array></value>
         </member>
         <member>
          <name>model</name>
          <value><string>ir.trigger</string></value>
         </member>
       </struct></value>
      </data></array></value>
  </param>
 </params>
</methodResponse>

More Details about XML RPC can be found here: http://en.wikipedia.org/wiki/XML-RPC
Comment by rico.glo...@gmail.com, Mar 19, 2011

BTW, if you consider XML-RPC bloated (well, i do), you might want to consider using JSON-RPC instead (Port 8000 by default). To use it, activate in trytond.conf:

# Activate the json-rpc protocol
#jsonrpc = False
# Configure the port for the json-rpc protocol to listen
#jsonport = 8000
# Configure the path of json-rpc data
#jsondata_path = /var/www/localhost/tryton

Sign in to add a comment
Powered by Google Project Hosting