1. OpenLib ORM Extension

1.1. Introduction

To use the OpenLib ORM Extension, you must import ExtendedOsv and Q classes:

from openlib.orm import ExtendedOsv, Q

If you want your objects to natively support the extension, make them inherit from ExtendedOsv:

class MyObject(osv.osv, ExtendedOsv):
    ...

Because OpenERP native objects does not inherit from ExtendedOsv, you can’t directly call the new methods on these objects pools. You will have to pass throught an object which inherits from ExtendedOsv.

1.2. The ExtendedOsv class

class openlib.orm.ExtendedOsv

Every object which inherit from this class can use the following methods. These methods support a django-like style and doesn’t require you to pass them cr, uid or context variables. These variables are recovered from the execution stack. This means that you must have variables named cr, uid, and context (optional) when you call these methods. Generally, these variables are passed by OpenERP.

Note

All the methods described below supports _cr, _uid and _context arguments to override the ones found automatically in the python stack. We use _ at the begin of arguments for methods which support django-like searching by arguments to avoid conflicts.

1.2.1. find

ExtendedOsv.find([q=None, _object=None, _offset=0, _limit=None, _order=None, _count=None, **kwargs])

This methods is an equivalent to the builtin search() method but let you use a django-like syntax or Q objects instead of the polish notation used in search().

Parameters:
Returns:

A list of integers, corresponding to ids found.

Note

If you specify one of the _limit, _offset, _order or _count arguments, they will be passed to search().

Examples

Find partners with name=’Agrolait’:

partners_ids = self.find(name='Agrolait', _object='res.partners')

Find partners with name=’Agrolait’ or ‘AsusTek’:

partners_ids = self.find(Q(name='Agrolait') | Q(name='AsusTek'), _object='res.partners')

In the case you are using find() on an object which inherit ExtendedOsv, you can omit the _object argument:

objects_ids = self.find(name='OK')

1.2.2. filter

ExtendedOsv.filter([value=None, _object=None, **kwargs])

This method is a kind of search-and-browse. It uses find() to search ids and then return the result of a browse() call so you can iterate over the results.

Parameters:
  • value – Can be a Q object or a list of ids.
  • kwargsSearch keywords if you don’t specify value.
Returns:

A list of objects as returned by browse().

If you specify a list of ids, find() is not called. The corresponding objects are immediatly returned.

Examples

Iterate over partners whose name starts with ‘A’:

for partner in self.filter(name__startswith='A', _object='res.partner'):
    ...

Almost same with a Q object:

for partner in self.filter(Q(name__startswith='A') | Q(name__startswith='B'), _object='res.partner'):
    ...

Iterate over a list of ids of one of our objects:

for obj in self.filter([1, 2, 3]):
    ...

1.2.3. get

ExtendedOsv.get([value=None, _object=None, **kwargs])

This method act like filter() but returns only one object. value can be one of the following :

  • An integer, then the object corresponding to this id is returned
  • A string, then the object with this XMLID is returned
  • A Q object, return the first object corresponding to the criteria.
  • None, then the first object corresponding to the search keywords is returned
Parameters:
  • value – The search criteria (see above)
  • kwargs – If value is None, search keywords
Returns:

An object as returned by browse() or None.

Examples

Returns the group whose XMLID is ‘group_employee’:

group = self.get('base.group_employee', _object='res.groups')

Returns the user with the id 1:

admin = self.get(1, _object='res.users')

Returns the first partner whose name is ‘Agrolait’:

partner = self.get(name='Agrolait', _object='res.partner')

1.2.4. get_pools

ExtendedOsv.get_pools(*args)

An equivalent of sel.pool.get which supports more than one argument.

Returns:A list of pool objects for each pool name passed as argument.

Example

partner_pool, config_pool = self.get_pools('res.partner', 'openlib.config')

1.2.5. xmlid_to_id

ExtendedOsv.xmlid_to_id(cr, uid, xmlid, context=None)

This method returns the database ID corresponding the xmlid passed, or None.

Note

This method does not uses automatic detection of cr, uid and context.

1.3. Query Objects

class openlib.orm.Q

This class let you create complex search query easily. It uses django-like keyword arguments to define search criteria. These objects can be combined with & or | and prefixed with - to negate them :

criteria = Q(name='Peter', age=12) | Q(name='Paul')

This example will be translated into this SQL request :

(name='Peter' AND age=12) OR name='Paul'

Prefixing Q objects with a minus sign will negate them:

criteria = -Q(name='Paul')

Which means name IS NOT Paul. You can create complex search expressions like this one :

criteria = (Q(name='Paul') | Q(name='Pierre)) & Q(age=12)) | -Q(age=12)

For a detailed description the keywords arguments, read Keywords arguments format.

1.4. Keywords arguments format

With OpenLib, Q objects and ExtendedOsv class methods supports keyword argument formatting to specify you search criteria. The simple form of the keyword argument is :

name='value'

Where name is the name of a column. But you can specify a lookup method using this syntax :

column__lookup='value'

Where lookup can be one of the following values :

  • exact - The default, same as not specifying a lookup method.
  • iexact - Same as exact, but case insensitive.
  • like - Performes an SQL LIKE with the value.
  • ilike - Same as like but case insensitive.
  • gt - Greater than, same as ‘>’.
  • lt - Lesser than, same as ‘<’.
  • ge - Geather than or equal, same as ‘>=’.
  • le - Lesser than or equal, same as ‘<=’.
  • startswith / istartswith - A shortcut to LIKE 'Value%'. The value is like-protected (special chars like % or _ are escaped).
  • endswith / iendswith - A shortcut to LIKE '%Value'. Value is like-protected.
  • contains / icontains - A shortcut to LIKE '%Value%'. Value is like-protected.

The column name can be separated with ‘__’ to represent a relation:

Q(partner__address__country__code='Fr')

Warning

If you have a column which have the same name that a lookup method, you must repeat it (xxx__exact__exact).

1.4.1. Examples

Using Q objects:

self.filter(Q(name__startswith='P') | Q(age__gt=12))

Using relation without Q objects:

self.find(address__city='Paris', _object='res.partners')