A few tips on using the OpenERP XML RPC API

I’ve been developing applications that talk to OpenERP via it’s API for a little while now and I figured it would be worth noting down some general pointers for using it. The API is used by all the UI clients for OpenERP so it definitely allows you to do everything that they do. It’s also got a reasonable amount of access to the data layer so you can do an awful lot via it. From simply creating interfaces to it, to streamlining a process with a slick UI, there are a lot of possibilities with it.

Here are my tips for developing with it,

  1. Run OpenERP with the --log-request and --log-response command line flags to see how OpenERP achieves it’s tasks. It’s also helpful to see what your application is sending.
  2. Don’t be afraid to read the code. Watching OpenERP is a great starting point, but sometimes you need to look at the code to understand what a parameter is for, or how it’s getting the data.
  3. Don’t be afraid to use the debugger. Putting --debug on the command line allows the python debugger to kick in when there is an exception. It also allows you to stick ‘import pdb; pdb.set_trace()’ onto a line in the code you want to investigate and drop into there in the debugger.
  4. Pass the context like you are told to, it makes life easier if you are setup to simply pass it along with your calls (but also be ready to add data to it). The context contains things like the language which is used for translations. You want your applications language to be consistent with any users of OpenERP itself otherwise things will get weird. Also note that some calls require extra information to be passed in via it. It’s not a completely opaque blob that you simply pass about between calls.
  5. Limit the columns you ask for. When you make a read call you can specify which columns you are interested in. Do that from the start or you’ll end up with performance problems later on. Once you have a partner with 1000’s of orders and invoices etc. a simple read of the res.partner will take a significant chunk of time if you aren’t limiting what you read from it.
  6. Don’t be afraid to extend OpenERP. Even if you aren’t a Python developer by trade, if you’re doing serious data modification you’re better off creating a module and calling a method on that than making lots of API calls. The main reason for that is to get everything into a single transaction. The other reason is speed.
  7. Be careful about filtering by calculated fields, they generally get turned into a ‘TRUE’ statement in the SQL. This can really screw things up when you have OR conditions in your filter. Use the --log-sql if you’re unsure what is happening.
  8. False is used for Null/None in the XML RPC
  9. Returning a dictionary from an OpenERP method via the API requires the keys to be strings. i.e you can’t simply return { id: quantity }. You’d need to do { str(id): quantity } to prevent a crash. None is also a no-no for dictionary values. Convert them to False if you want to be consistent with OpenERP.
  10. Formatting of numbers to n decimal places is largely done client side. OpenERP provides you all the info you need, but you need to deal with that yourself.
  11. Beware of gapless ir.sequence sequences in batch jobs. They have a high potential for causing contention.
Tagged

10 thoughts on “A few tips on using the OpenERP XML RPC API

  1. Chris says:

    Hi,
    Could you explain what you mean by “Beware of gapless ir.sequence sequences in batch jobs” ?

    What is it exactly ?

    Regarding the key string requirement (i would say a “bug” ?)… how do you if you don’t modify / add your own module ?

    For instance, if i do a standard “price_get” method (in order to calculate the price of a product)… I face the “key string” problem… and I receive a nice error message from OpenERP !

    I bypass this issue, by using a… JSON query. Am i wrong ?

    Last but not least… in standard… it’s impossible to process queries with a JOIN like in SQL.

    For instance : without adding / modify a module, I dont how to get :

    -the lines of purchases orders that are “confirmed”… but with the flag “invoiced” to false (in the purchase.order table), which would be 1 query in SQL.. but with XMLRPC… i need to get all the purchase orders lines that are “confirmed”, then take their ID, then make a search with those IDs on purchase.order to screen out the flag invoiced…

    It’s a mess.

  2. colinnewell says:

    The gapless sequences ensure that sequence numbers have no gaps. i.e. SO0001, SO0002, SO0003 … Rather than say skipping SO0003. They are only really used on the account moves by default and they ensure that the account movements have consistent sequential names. With the normal sequences if a transaction asks for a number, then needs to rollback because of some other problem, the sequence doesn’t worry about it, that number just gets skipped in the sequence. With the gapless sequences a lock is obtained on the sequence number field so the next process will have to wait until the current transaction is done before it can read it, and therefore if there is a rollback the number won’t be lost. The downside is that if the transaction takes a long time this can block things for quite a while. It also increases the chances of long running processes that depend on them from bailing because of a contention.

    I hadn’t really come across any places where the key string issue appeared to be an issue in the OpenERP code, but you appear to be right that that method does indeed suffer from that problem. You quite often find methods that were never expected to be called by the users of the API but are just about callable, but not won’t quite work. I have generally added extra methods in my own method to call them and make them usable where necessary. The json api might avoid that particular issue.

    The search is quite easy, joins on search terms are done automatically and fairly simply. The query you want is easily done like this,

    server.execute(db, uid, pwd, 'purchase.order.line', 'search', [('order_id.invoiced', '=', '1') ])
    

    As you can see here, you specify the relationship field name ‘order_id’, then the field you want to query on, ‘invoiced’. You can quite often descend through several models and it will do the right thing.

  3. Chris says:

    Brillant ! Thanks for the tip. I never saw this on all the documentation. How did you find it ?

    Speaking about doc, that’s quite an issue with OpenERP. It’s really poor. So people have to spend hours and hours perusing websites, blogs (yours !), tidbits, forums, compounded by the problem of version number… it’s exhausting. ;-)

    Anyway, let’s hope once they release version 8, they will have more time and ressources to spend on doc work.

  4. colinnewell says:

    Version 6′s documentation seemed okay if limited, after that it seemed to struggle to keep up. Some times it can be worth looking in the different version of the documentation too as some parts are the same.

    This is the page I normally refer back to when I’m looking for the details on how search works – ORM Methods. Apart from that I just look at what is happening in OpenERP itself by watching the debug log.

  5. Chris says:

    Is it possible to do the same with the “read” method ? To read a field linked by a join on a another table ?

  6. colinnewell says:

    Unfortunately I don’t believe it is. If you do find a way I’d be interested to know about it. When I’ve really needed to do things that the ORM can not do I’ve added a method to a module that implements it in SQL.

    • Chris says:

      It’s rather weird to allow to make a join search, but not a read. I’ve tried many combinations with the read method, but no success.

      I know that it’s piece of cake to create a custom module that would process SQL queries, but why it’s not available in standard ?

      That’s a short coming, and I’m wondering if it’s not the dark side of OpenERP’s model : “oh people can do it with a custom module… so no need to bother”…

      And eventually, everybody… is recreating the wheel, each time, by themselves, over and over again !

      I mean we are not talking here about a “luxury” item or a “gimmick” function… but rather an essential tool.

      So to go back to my example about purchase_order_line and purchase_order… I can do the search now, but I can’t display -in standard- fields in both table with the IDs I receive. ;-)

      Anyway. End of the rant.

      • colinnewell says:

        Keep an eye on their release notes and roadmaps. I have heard tell of improved ORM’s etc. in the future, but I haven’t really paid too much attention because I only really care about what is current and stable.

  7. Murali says:

    Can we call custom methods written in any object (e.g. res_partner), other than ORM methods using XML RPC.

    • colinnewell says:

      Within reason yes. Assuming the method hasn’t been marked private (those starting with a _), and has a method signature that is roughly compatible with remote execution (normally starting (self, cr, uid, …)) then it is possible to call most methods. Some methods aren’t expecting to be called via the API and so don’t conform to the standards expected, but you can generally try it and see if it works. Methods that return nothing will cause OpenERP to throw an error (after executing the function) and those that return a dictionary containing numeric keys will also cause OpenERP to throw an error.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 58 other followers