Toggle navigation

ORM API - Odoo 10.0

Наборы записей

Добавлено в версии 8.0: На этой странице представлен новый API, добавленный в Odoo 8.0, который станет основным API разработки в будущем. Здесь также предоставлена информация о переносе или переходе со «старого API» версии 7 и более ранних, но вы не найдете здесь документации на старый API. Информацию о старом API ищите в соответствующих документах.

Взаимодействие с моделями данных и записями осуществляется с помощью Наборов Записей (НЗ) - отсортированного набора записей той же модели данных.

Методы, определенные для модели данных, выполняются над НЗ, а их self и представляет собой экземпляр НЗ:

class AModel(models.Model):
    _name = 'a.model'
    def a_method(self):
        # self can be anywhere between 0 records and all records in the
        # database
        self.do_operation()

Перебор НЗ приведет к созданию новых НЗ состоящих из одной записи (ОЗ), данный механизм можно сравнить с перебором строки Python который формирует строки из одного символа:

def do_operation(self):
    print self # => a.model(1, 2, 3, 4, 5)
    for record in self:
        print record # => a.model(1), then a.model(2), then a.model(3), ...

Доступ к полям

НЗ предоставляют интерфейс "Active Record": поля моделей данных могут считываться и записываться непосредственно из записи, но только для ОЗ (НЗ состоящие из одиночной записи). Присвоение значения полю запускает обновление базы данных:

>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob

Попытка прочитать или записать поле сразу в нескольких записях вызовет ошибку.

Доступ к реляционному полю(Many2one, One2many, Many2many) всегда возвращает НЗ, пустой если поле не задано.

Запись кеша и предварительная выборка

Odoo поддерживает кеш для полей записей, так что не каждый доступ к полям вызывает запрос базы данных, что ужасно сказывалось бы на производительности. Следующий пример запрашивает базу данных только для первого выражения:

record.name             # first access reads value from database
record.name             # second access gets value from cache

Чтобы не считывать одно поле из одной записи за раз, Odoo выполняет предварительную выборку записей и полей, следуя некоторым эвристикам, чтобы получить хорошую производительность. Как только поле должно быть прочитано в данной записи, ORM фактически считывает это поле в большем НЗ и сохраняет возвращаемые значения в кеше для последующего использования. Унаследованный НЗ обычно представляет собой ИЗ, из которого запись выбирается путем перебора. Более того, все простые хранимые поля (boolean, integer, float, char, text, date, datetime, selection, many2one) извлекаются целиком; Они соответствуют столбцам таблицы модели данных и эффективно извлекаются в одном запросе.

Рассмотрим следующий пример, где partners - набор записей из 1000 записей. Без предварительной выборки цикл будет выполнять 2000 запросов к базе данных. При предварительной выборке выполняется только один запрос:

for partner in partners:
    print partner.name          # first pass prefetches 'name' and 'lang'
                                # (and other fields) on all 'partners'
    print partner.lang

Предварительная выборка также работает на вторичных записях: при чтении значений реляционных полей (которые являются записями) подписываются на будущую предварительную выборку. При обращении к одной из этих вторичных записей происходит предварительная выборка всех вторичных записей из одной и той же модели данных. В следующем примере генерируются только два запроса: один для партнеров и один для стран:

countries = set()
for partner in partners:
    country = partner.country_id        # first pass prefetches all partners
    countries.add(country.name)         # first pass prefetches all countries

Операции над НЗ

НЗ не изменяемы, но наборы одной и той же модели могут комбинироваться с использованием различных операторов для НЗ, возвращая новые НЗ. Данные операторы не сохраняют порядок сортировки записей внутри НЗ.

  • record in set возвращает запись (которая должна быть набором из 1 элемента) если таковая присутствует присутствует в НЗ set. record not in set - это обратная операция

  • set1 <= set2 и set1 < set2 возвращает НЗ set1 если он входит НЗ set2 (resp. strict)

  • set1 >= set2 and set1 > set2 возвращает НЗ set1 если он включает в себя НЗ set2 (resp. strict)

  • set1 | set2 возвращает объединение двух НЗ, новый НЗ содержит все записи, имеющиеся каждом источнике

  • set1 & set2 возвращает пересечение двух НЗ, новый НЗ содержит только те записи которые содержатся одновременно в обоих источниках

  • set1 - set2 возвращает новый НЗ, содержащий только записи НЗ set1, которые не входят в НЗ set2

Другие операции с НЗ

НЗ это итерируемый объект, поэтому обычные инструменты Python доступны для работы с ним (map(), sorted(), ifilter(), ...) однако они возвращают либо list или iterator, удаляя возможность вызывать методы для возвращенных результатов, или использовать операции НЗ.

Поэтому НЗ предоставляют такие операции, которые возвращают объекты НЗ (когда это возможно):

filtered()

Возвращает НЗ, содержащий только записи, удовлетворяющие предоставленной предикатной функции. Предикат может также быть строкой для отфильтрованный по полю, являющемуся истинным или ложным:

# only keep records whose company is the current user's
records.filtered(lambda r: r.company_id == user.company_id)

# only keep records whose partner is a company
records.filtered("partner_id.is_company")
sorted()

Возвращает НЗ, отсортированный по предоставленной ключевой функции. Если ключ не указан, используется порядок сортировки установленный для модели данных по умолчанию:

# sort records by name
records.sorted(key=lambda r: r.name)
mapped()

Применяет предоставленную функцию к каждой записи в НЗ, возвращает НЗ, если результаты являются НЗ:

# returns a list of summing two fields for each record in the set
records.mapped(lambda r: r.field1 + r.field2)

Предоставленная функция может быть строкой для получения значений полей:

# returns a list of names
records.mapped('name')

# returns a recordset of partners
record.mapped('partner_id')

# returns the union of all partner banks, with duplicates removed
record.mapped('partner_id.bank_ids')

Окружение

Класс Environment хранит различные контекстные данные, используемые ORM: курсор базы данных (формирования запросов к базе данных), текущий пользователь (для проверки прав доступа) и текущий контекст (хранение произвольных метаданных). В окружении также хранятся кэши.

Все НЗ имеют окружение, доступ к которой можно получить с помощью env и предоставляет доступ к текущему пользователю (user), курсору (cr) или контексту(context):

>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)

При создании НЗ из другого набора записей окружение наследуется. Окружение может быть использовано для получения пустого НЗ в другой модели данных а так же для формирования запроса к модели:

>>> self.env['res.partner']
res.partner
>>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)

Изменение окружения

Окружение может быть скорректировано на основании НЗ. Данная операция возвращает новую версию НЗ, используя измененное окружение.

sudo()

Создает новое окружение для данного НЗ с правами доступа указанного пользователя, если пользователь не указан, то предоставляются права администратора, (это может быть полезно для обходя ограничений безопасности в ряде случаев), возвращает копию НЗ, который работает в новом окружении:

# create partner object as administrator
env['res.partner'].sudo().create({'name': "A Partner"})

# list partners visible by the "public" user
public = env.ref('base.public_user')
env['res.partner'].sudo(public).search([])
sudo()
  1. Может принимать один позиционный параметр, который заменяет контекст текущего окружения

  2. Может принимать любое количество параметров по ключевому слову, которые добавляются либо в контекст текущего окружения, либо в контекст, заданный во время шага 1

# look for partner, or create one with specified timezone if none is
# found
env['res.partner'].with_context(tz=a_tz).find_or_create(email_address)
with_env()

Полностью заменяет существующее окружение

Базовые методы ORM

search()

Принимает параметры поиска в виде домена, и возвращает НЗ который удовлетворяют условиям поиска. Может возвращать часть НЗ совпадающих записей (параметры offset и limit) и может быть отсортирован (параметр order):

>>> # searches the current model
>>> self.search([('is_company', '=', True), ('customer', '=', True)])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)
>>> self.search([('is_company', '=', True)], limit=1).name
'Agrolait'
create()

Принимает несколько значений полей и возвращает НЗ, содержащий созданную запись:

>>> self.create({'name': "New Name"})
res.partner(78)
write()

Принимает несколько значений полей, записывает их во все записи в своем НЗ. Ничего не возвращает:

self.write({'name': "Newer Name"})
browse()

Принимает идентификатор базы данных или список идентификаторов и возвращает НЗ, полезен, когда идентификаторы записей получены извне Odoo (например запрос-ответ от внешней системы) или когда вызываете методы старого API:

>>> self.browse([7, 18, 12])
res.partner(7, 18, 12)
exists()

Возвращает новый НЗ, содержащий только записи, существующие в базе данных. Может использоваться для проверки того, существует ли запись (например, полученная извне):

if not record.exists():
    raise Exception("The record has been deleted")

или после вызова метода, который мог бы удалить некоторые записи:

records.may_remove_some()
# only keep records which were not deleted
records = records.exists()
ref()

Метод окружения, возвращающий запись, соответствующую предоставленному external id:

>>> env.ref('base.group_public')
res.groups(2)
ensure_one()

Проверяет, что НЗ являлся ОЗ (содержит только одну запись), в противном случае возникает ошибка:

records.ensure_one()
# is equivalent to but clearer than:
assert len(records) == 1, "Expected singleton"

Создание моделей данных

Поля модели данных определяются как ее атрибуты:

from odoo import models, fields
class AModel(models.Model):
    _name = 'a.model.name'

    field1 = fields.Char()

По умолчанию метка поля (видимое пользователем имя) является версией имени поля написанной с большой буквы, это может быть переопределено параметром `string:

field2 = fields.Integer(string="an other field")

Для различных типов полей и их параметрах смотрите the fields reference.

Значения по умолчанию определяются как параметры полей с присвоенными им значениями:

a_field = fields.Char(default="a value")

или функция, которая должна вычислять и возвращать это самое значение по умолчанию:

def compute_default_value(self):
    return self.get_value()
a_field = fields.Char(default=compute_default_value)

Вычисляемые поля

Значение полей может быть вычеслено (вместо того, чтобы читать их прямо из базы данных) с помощью параметра compute. Он должен присвоить вычисленное значение полю. Если он использует значения других полей, он должен указать эти поля, используя depends():

from odoo import api
total = fields.Float(compute='_compute_total')

@api.depends('value', 'tax')
def _compute_total(self):
    for record in self:
        record.total = record.value + record.value * record.tax
  • зависимости могут быть указанны в виде ссылки на поле, путь к которому вы описываете через точки:

    @api.depends('line_ids.value')
    def _compute_total(self):
        for record in self:
            record.total = sum(line.value for line in record.line_ids)
    
  • вычисляемые поля по умолчанию не сохраняются, их значения вычисляются и возвращаются по запросу. Параметр store = True сохранит их значение в базе данных и автоматически включит поиск

  • поиск по вычисленному полю также можно включить, установив параметр search. Значение - это имя метода, возвращающее Домены:

    upper_name = field.Char(compute='_compute_upper', search='_search_upper')
    
    def _search_upper(self, operator, value):
        if operator == 'like':
            operator = 'ilike'
        return [('name', operator, value)]
    
  • для разрешения значений setting в вычислимых полях используйте параметр inverse. Это имя функции, задача которой откатить вычисления и установить в соответствующие поля нужные значения:

    document = fields.Char(compute='_get_document', inverse='_set_document')
    
    def _get_document(self):
        for record in self:
            with open(record.get_document_path) as f:
                record.document = f.read()
    def _set_document(self):
        for record in self:
            if not record.document: continue
            with open(record.get_document_path()) as f:
                f.write(record.document)
    
  • значения для нескольких полей могут быть вычислены одновременно одним и тем же методом, просто используйте его во всех полях и присвойте нужные значения для каждого из них:

    discount_value = fields.Float(compute='_apply_discount')
    total = fields.Float(compute='_apply_discount')
    
    @depends('value', 'discount')
    def _apply_discount(self):
        for record in self:
            # compute actual discount from discount percentage
            discount = record.value * record.discount
            record.discount_value = discount
            record.total = record.value - discount
    

оnchange: обновление интерфейса на лету

Когда пользователь изменяет значение поля в форме (но еще не сохранил форму), бывает, что полезно автоматически обновлять другие поля на основе введенного им значения, например, обновлять итоговую сумму при изменении значения налога или добавления еще одной позиции в счет.

  • Вычисляемые поля автоматически проверяются и пересчитываются, им не требуется onchange

  • для не вычисляемых полей, используется декоратор onchange() чтобы предоставить новые значения полей:

    @api.onchange('field1', 'field2') # if these fields are changed, call method
    def check_change(self):
        if self.field1 < self.field2:
            self.field3 = True
    

    изменения, выполненные во время работы этого метода, затем отправляются в клиентскую программу и становятся видимыми для пользователя

  • Как вычисляемые поля так и принадлежащая новому API функция onchange автоматически вызывается клиентом без необходимости добавлять их в представлениях

  • Можно исключить триггер который вызывает их работу для определенного поля, добавив on_change="0" в представлении:

    <field name="name" on_change="0"/>
    

    обновления интерфейса не будут происходить, если поле редактируется пользователем, даже если в этом поле есть вычисляемые поля или явный вызов onchange.

Использование SQL

В окружении атрибут cr является курсором для выполнения транзакции в текущей базе данных и позволяет напрямую выполнять SQL, также применяется для запросов, которые трудно выразить с помощью ORM (например, сложные join'ы), либо для производительности причины:

self.env.cr.execute("some_sql", param1, param2, param3)

Поскольку модели данных используют один и тот же курсор, а класс Environment содержит различные кэши, эти кеши должны быть недействительными при изменении базы данных с помощью чистого SQL, или дальнейшее использование моделей может стать некогерентным. Необходимо очищать кеши при использовании CREATE, UPDATE или DELETE в SQL, но не SELECT (который просто читает базу данных).

Очистка кэшей может выполняться с использованием метода invalidate_all() класса Environment object.

Совместимость между новым API и старым API

В настоящее время Odoo переходит со старого (менее упорядоченного) API, возможно потребуется выполнение ряда операций вручную при переходе от одного API к другому:

  • Уровни RPC (как XML-RPC, так и JSON-RPC) выражаются в терминах старого API, методы, выраженные чисто в новом API, недоступны через RPC

  • переопределенные методы могут быть вызваны из более старых фрагментов кода, все еще написанных на старом API

Здесь представлены наиболее крупные различия между старыми и новыми API:

  • значения класса Environment (курсор, идентификатор пользователя и контекст) передаются методу явным образом

  • записи (ids) передаются явным образом в методы и, возможно, не передаются вообще

  • методы, как правило, работают со списками идентификаторов вместо НЗ

По умолчанию предполагается, что методы используют новый API и не могут вызываться из старого API.

Два декоратора могут вызвать новый метод для старого API:

model()

метод предоставляется как не использующий идентификаторы, его НЗ, как правило, пуст. Его сигнатура "старого API" выглядит следующим образом cr, uid, *arguments, context:

@api.model
def some_method(self, a_value):
    pass
# can be called as
old_style_model.some_method(cr, uid, a_value, context=context)
multi()

метод предоставляется как принимающий список идентификаторов (возможно, пустых), его сигнатура «старого API» выглядит следующим образом cr, uid, ids, *arguments, context:

@api.multi
def some_method(self, a_value):
    pass
# can be called as
old_style_model.some_method(cr, uid, [id1, id2], a_value, context=context)

Поскольку новые API-интерфейсы склонны возвращать НЗ, а старые API-интерфейсы возвращают списки идентификаторов, поэтому существует декоратор, управляющий этим:

returns()

предполагается, что функция возвращает НЗ, первым параметром должно быть имя модели данных которой принадлежит НЗ или self (для текущей модели).

не будет эффекта, если метод вызывается в новом API, но НЗ будет преобразован в список идентификаторов при вызове из старого API:

>>> @api.multi
... @api.returns('self')
... def some_method(self):
...     return self
>>> new_style_model = env['a.model'].browse(1, 2, 3)
>>> new_style_model.some_method()
a.model(1, 2, 3)
>>> old_style_model = pool['a.model']
>>> old_style_model.some_method(cr, uid, [1, 2, 3], context=context)
[1, 2, 3]

Ссылки на модели данных

class odoo.models.Model(pool, cr)[исходный код]

Основной суперкласс для регулярных моделей Odoo, поддерживающих базу данных.

Одоо модели создаются наследованием от этого класса

class user(Model):
    ...

Позже система создаст экземпляр класса один раз для каждой базы данных (на которой установлен модуль класса).

Структурные атрибуты

_name

наименование бизнес-объекта, в dot-нотации (в пространстве имен модуля)

_rec_name

Альтернативное поле для использования в качестве наименования, используемое osv’s name_get() (по умолчанию: 'name')

_inherit
  • Если атрибут _name указан, то он должен содержать имена родительских моделей данных, которые он наследует. Может быть str, если происходит наследование от одного родителя

  • Если атрибут _name не указан, то происходит расширение конкретной модели данных

Смотрите Наследование и расширение.

_order

Поле указывающее на порядок сортировки при поиске указывать не требуется (по умолчанию сортировка происходит по: 'id')

Type
str
_auto

Должна ли создаваться таблица базы данных (по умолчанию: True)

Если установлено значение False, переопределите init`() для создания таблицы базы данных

_table

Имя таблицы, с которой связана модель данных, созданной при использовании атрибута _auto, автоматически генерируется по умолчанию.

_inherits

словарь, сопоставляющий _name родительских бизнес-объектов с именами соответствующих полей внешнего ключа для использования:

_inherits = {
    'a.model': 'a_field_id',
    'b.model': 'b_field_id'
}

реализует композиционное наследование: новая модель данных предоставляет все поля модели _inherits, но не хранит ни одного из них: сами значения остаются в связанной записи.

_constraints

Список (constraint_function, message, fields), определяющий ограничения для Python. Список полей является ориентировочным

Не рекомендуется, начиная с версии 8.0: use constrains()

_sql_constraints

список триплетов (name, sql_definition, message) , определяющих SQL-ограничения при создании резервной таблицы

_parent_store

Атрибут parent_left and [UNKNOWN NODE problematic] для включения быстрых иерархических запросов к записям текущей модели (по умолчанию: False)

Type
bool

CRUD

create(vals) → record[исходный код]

Создает новую запись для модели.

Новая запись инициализируется с использованием значений из `` vals`` и при необходимости из: meth: [UNKNOWN NODE title_reference].

Параметры
vals (dict) -- Значения для полей модели, как словарь :: {'field_name': field_value, ...} see: meth: [UNKNOWN NODE title_reference] для деталей
Результат
Новая запись создана
Исключение
  • AccessError --
    • Если у пользователя нет прав на создание объекта

    • Если пользователь пытается обойти правила доступа для создания на запрошенном объекте

  • ValidateError -- Если пользователь пытается ввести недопустимое значение для поля, которое не выбрано
  • UserError -- Если в иерархии объектов будет создан цикл в результате операции (такой как установка объекта как собственного родителя)
browse([ids]) → records[исходный код]

Возвращает набор записей для идентификаторов, предоставленных в качестве параметра в текущей среде.

Не может принимать идентификаторы, одиночный идентификатор или последовательность идентификаторов.

Удаляет записи текущего набора

Исключение
  • AccessError --
    • Если у пользователя нет прав развязки на запрошенном объекте

    • Если пользователь пытается обойти правила доступа для развязки на запрошенном объекте

  • UserError -- Если запись является свойством по умолчанию для других записей
write(vals)[исходный код]

Обновляет все записи в текущем наборе с предоставленными значениями.

Параметры
vals (dict) -- Поля для обновления и значение для них, например: :: {'foo': 1, 'bar': "Qux"} установите поле foo в 1, ​​а поле Bar в "Qux" если они действительны (иначе это вызовет ошибку).
Исключение
  • AccessError --
    • Если у пользователя нет прав на запись для запрашиваемого объекта

    • Если пользователь пытается обойти правила доступа для записи на запрошенном объекте

  • ValidateError -- Если пользователь пытается ввести недопустимое значение для поля, которое не выбрано
  • UserError -- Если в иерархии объектов будет создан цикл в результате операции (такой как установка объекта как собственного родителя)
  • Для числовых полей (: class: [UNKNOWN NODE title_reference],: class:` ~ odoo.fields.Float`) значение должно быть соответствующего типа

  • Для: class: [UNKNOWN NODE title_reference], значение должно быть: class:` python: bool`

  • Для: class: [UNKNOWN NODE title_reference], значение должно соответствовать значениям выбора (обычно: class:` python: str`, иногда: class: [UNKNOWN NODE title_reference])

  • Для: class: [UNKNOWN NODE title_reference], значение должно быть идентификатором базы данных для записи

  • Другие нереляционные поля используют строку для значения

  • : Class: [UNKNOWN NODE title_reference] и: class:` ~ odoo.fields.Many2many` используют специальный формат "команды" для управления набором записей, хранящихся в / связанных с этим полем.

    Этот формат представляет собой список триплетов, выполняемых последовательно, где каждый триплет является командой, выполняемой по набору записей. Не все команды применяются во всех ситуациях. Возможные команды:

    Значения(s)

    Добавляет новую запись, созданную из предоставленного `` значения`` dict.

    `` (1, id, значения) ``

    Обновляет существующую запись id `` id`` со значениями в `` значения``. Нельзя использовать в: мет: [UNKNOWN NODE title_reference].

    Ид

    Удаляет запись id `` id`` из набора, а затем удаляет его (из базы данных). Нельзя использовать в: мет: [UNKNOWN NODE title_reference].

    Ид

    Удаляет запись id `` id`` из набора, но не удаляет его. Нельзя использовать: class: [UNKNOWN NODE title_reference]. Нельзя использовать в: мет: [UNKNOWN NODE title_reference].

    Ид

    Добавляет существующую запись id `` id`` в набор. Нельзя использовать: class: [UNKNOWN NODE title_reference].

    (5, _, _)

    Удаляет все записи из набора, что эквивалентно использованию команды `` 3`` для каждой записи явно. Нельзя использовать: class: [UNKNOWN NODE title_reference]. Нельзя использовать в: мет: [UNKNOWN NODE title_reference].

    Ids1

    Заменяет все существующие записи в наборе списком `` ids``, что эквивалентно использованию команды `` 5``, за которой следует команда `` 4`` для каждого `` id`` в `` ids``.

read([fields])[исходный код]

Читает запрошенные поля для записей в `` self``, низкоуровневом / RPC-методе. В коде Python предпочитайте: meth: [UNKNOWN NODE title_reference].

Параметры
fields -- Список имен полей для возврата (по умолчанию все поля)
Результат
Список словарей, отображающих имена полей в их значениях, с одним словарем на запись
Исключение
AccessError -- Если у пользователя нет прав на чтение некоторых из данных записей
read_group(domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True)[исходный код]

Получить список записей в виде списка, сгруппированных по заданным полям `` groupby``

Параметры
  • domain -- Список, определяющий критерии поиска [['field_name', 'operator', 'value'], ...]
  • fields (list) -- Список полей, представленных в виде списка, указанного на объекте
  • groupby (list) -- Список групп по описаниям, по которым записи будут сгруппированы. Групповое описание представляет собой либо поле (тогда оно будет сгруппировано по этому полю), либо поле 'field: groupby_function'. Прямо сейчас единственными поддерживаемыми функциями являются «день», «неделя», «месяц», «квартал» или «год», и они имеют смысл только для полей даты и времени.
  • offset (int) -- Необязательное количество записей для пропуска
  • limit (int) -- Необязательное максимальное количество возвращаемых записей
  • orderby (list) -- Необязательная спецификация `` order by``, для переопределения естественного порядка сортировки групп, см. Также: py: meth: [UNKNOWN NODE title_reference] (поддерживается только для многих полей в настоящее время)
  • lazy (bool) -- Если true, результаты группируются только первой группой, а остальные groupbys помещаются в ключ __context. Если false, все groupbys выполняются за один вызов.
Результат
Список словарей (один словарь для каждой записи), содержащий: * значения полей, сгруппированных по полям в аргументе `` groupby`` * __domain: список кортежей, определяющих критерии поиска * __context: словарь с аргументом типа `` groupby``
Тип результата
[{'field_name_1': value, ...]
Исключение
AccessError --
  • Если пользователь не имеет прав на запрашиваемый объект

  • Если пользователь пытается обойти правила доступа для чтения на запрошенном объекте

Поиск

search(args[, offset=0][, limit=None][, order=None][, count=False])[исходный код]

Ищет записи, основанные на `` args``: ref: [UNKNOWN NODE title_reference].

Параметры
  • args -- : Ref: [UNKNOWN NODE title_reference]. Используйте пустой список для соответствия всем записям.
  • offset (int) -- Количество игнорируемых результатов (по умолчанию: нет)
  • limit (int) -- Максимальное количество возвращаемых записей (по умолчанию: все)
  • order (str) -- Строка сортировки
  • count (bool) -- Если «Истина», только подсчитывает и возвращает количество совпадающих записей (по умолчанию: False)
Результат
Не более [UNKNOWN NODE title_reference] записей, соответствующих критериям поиска
Исключение
AccessError --
  • Если пользователь пытается обойти правила доступа для чтения на запрошенном объекте.

search_count(args) → int[исходный код]

Возвращает количество записей в текущем совпадении модели: ref: [UNKNOWN NODE title_reference].

Искать записи, у которых есть отображаемое имя, соответствующее заданному шаблону `` name``, по сравнению с указанным `` operator``, а также соответствие необязательной области поиска (`` args``).

Это используется, например, для предоставления предложений, основанных на частичном значении для реляционного поля. Иногда можно рассматривать как обратную функцию: meth: [UNKNOWN NODE title_reference], но это не гарантируется.

Этот метод эквивалентен вызову: meth: [UNKNOWN NODE title_reference] с поисковым доменом на основе` [UNKNOWN NODE title_reference], а затем: meth:` ~ .name_get` по результату поиска.

Параметры
  • name (str) -- Шаблон имени, который нужно сопоставить
  • args (list) -- Необязательный домен поиска (см.: Meth: [UNKNOWN NODE title_reference] для синтаксиса), указав дальнейшие ограничения
  • operator (str) -- Domain для сопоставления `` name``, например `` 'like'`` или ' = '.
  • limit (int) -- Необязательное максимальное количество возвращаемых записей
Тип результата
list
Результат
Список пар `` (id, text_repr) `` для всех совпадающих записей.

Операции с НЗ

ids

Список фактических идентификаторов записей в этом наборе записей (игнорирует идентификаторы-заполнители для создаваемых записей)

ensure_one()[исходный код]

Проверяет, что текущий recorset содержит одну запись. В противном случае возникает исключение.

exists() → records[исходный код]

Возвращает подмножество записей в `` self``, которые существуют, и помечает удаленные записи как таковые в кеше. Его можно использовать в качестве теста на записях

if record.exists():
    ...

По соглашению, новые записи возвращаются как существующие.

filtered(func)[исходный код]

Выберите записи в `` self``, чтобы `` func (rec) `` было истинно, и верните их как набор записей.

Параметры
func -- Функция или разделенная точками последовательность имен полей
sorted(key=None, reverse=False)[исходный код]

Возвращает набор записей `` self``, упорядоченный `` key``.

Параметры
  • key -- Либо функцию одного аргумента, который возвращает ключ сравнения для каждой записи, либо имя поля, либо `` None``, в этом случае записи упорядочиваются в соответствии с заказом модели по умолчанию
  • reverse -- Если `` True``, вернуть результат в обратном порядке
mapped(func)[исходный код]

Примените `` func`` во всех записях в `` self``, и верните результат в виде списка или набора записей (если `` func`` возвращает записи). В последнем случае порядок возвращаемого набора записей произволен.

Параметры
func -- Функция или разделенная точками последовательность имен полей (строка); Любое ложное значение просто возвращает набор записей `` self``

Обмен окружением

sudo([user=SUPERUSER])[исходный код]

Возвращает новую версию этого набора записей, прикрепленного к предоставленному пользователю.

По умолчанию это возвращает набор записей `` SUPERUSER``, где контроль доступа и правила записи обходят.

with_context([context][, **overrides]) → records[исходный код]

Возвращает новую версию этого набора записей, присоединенного к расширенному контексту.

Расширенным контекстом является либо предоставленный контекст, в котором объединены `` overrides``, либо * текущий * контекст, в котором объединены `` overrides`` например:

# current context is {'key1': True}
r2 = records.with_context({}, key2=True)
# -> r2._context is {'key2': True}
r2 = records.with_context(key2=True)
# -> r2._context is {'key1': True, 'key2': True}
with_env(env)[исходный код]

Возвращает новую версию этого набора записей, прикрепленного к предоставленной среде.

Запросы полей и представлений

fields_get([fields][, attributes])[исходный код]

Возвращает определение каждого поля.

Возвращаемое значение - словарь (обозначается именем поля) словарей. Включены поля _inherits'd. Атрибуты string, help и selection (если присутствуют) транслируются.

Параметры
  • allfields -- Список полей для документа, все, если они пусты или не указаны
  • attributes -- Список атрибутов описания, возвращаемых для каждого поля, все, если они пусты или не указаны
fields_view_get([view_id | view_type='form'])[исходный код]

Получить подробный состав запрашиваемого представления, например поля, модель, вид архитектуры

Параметры
  • view_id -- Идентификатор представления или Нет
  • view_type -- Тип представления, возвращаемого, если view_id равно None ('form', 'tree', ...)
  • toolbar -- True для включения контекстных действий
  • submenu -- Устарело
Результат
Словарь, описывающий состав запрошенного представления (включая унаследованные представления и расширения)
Исключение
  • AttributeError --
    • Если унаследованное представление имеет неизвестную позицию для работы с другими, чем «до», «после», «внутри», «заменить»,

    • Если в родительском представлении обнаружен какой-либо тег, отличный от 'position'

  • Invalid ArchitectureError -- Если есть вид, отличный от формы, дерева, календаря, поиска и т. Д., Определенных в структуре

Различные методы

default_get(fields) → default_values[исходный код]

Возвращайте значения по умолчанию для полей в `` fields_list``. Значения по умолчанию определяются контекстом, пользовательскими настройками по умолчанию и самой моделью.

Параметры
fields_list -- Список имен полей
Результат
Словарь, отображающий каждое имя поля в соответствующее значение по умолчанию, если оно есть.
copy(default=None)[исходный код]

Дублировать запись `` self``, обновляя ее значениями по умолчанию

Параметры
default (dict) -- Словарь значений поля для переопределения в исходных значениях скопированной записи, например: `` {'field_name': overridden_value, ...} ``
Результат
новая запись
name_get() → [(id, name), ...][исходный код]

Возвращает текстовое представление для записей в `` self``. По умолчанию это значение поля `` display_name``.

Результат
Список пар `` (id, text_repr) `` для каждой записи
Тип результата
list(tuple)
name_create(name) → record[исходный код]

Создайте новую запись, вызвав: meth: [UNKNOWN NODE title_reference], указав только одно значение: отображаемое имя новой записи.

Новая запись будет инициализироваться с любыми значениями по умолчанию, применимыми к этой модели или предоставляемыми через контекст. Применяется обычное поведение: meth: [UNKNOWN NODE title_reference].

Параметры
name -- Отображаемое имя создаваемой записи
Тип результата
Результат
Параметр: meth: [UNKNOWN NODE title_reference] для созданной записи

Автоматические поля

id

Идентификатор field

_log_access

Должны быть созданы поля для журналирования действий пользователей (create_date, write_uid, ...) (по умолчанию: True)

create_date

Дата создания записи

Type

ласс: [UNKNOWN NODE title_reference]

create_uid

Реляционное поле для пользователя, создавшего запись

Type
res.users
write_date

Дата последнего изменения записи

Type

ласс: [UNKNOWN NODE title_reference]

write_uid

Реляционное поле для пользователя, который последним изменил запись

Type
res.users

Зарезервированные имена полей

Несколько имен полей зарезервированы для предопределенных сценариев, которые отличаются от автоматически заполняемых полей. Они должны быть определены в модели данных, когда настраивается желаемое поведение:

name

значение по умолчанию для _rec_name, используется для отображения записей в контексте, где требуется репрезентативное "наименование".

Type
active

позволяет отключать глобальную видимость записи, если параметр active установлен на False, запись невидима в большинстве поисковых запросов и подсказок

sequence

Изменяемые критерии сортировки, дпозволяет перетаскивать записи модели данных в представлениях в виде списка

state

этапы жизненного цикла объекта, используемые атрибутом состояния в классе : fields

parent_id

используется для упорядочивания записей в древовидной структуре и включения оператора child_of в доменах

parent_left

используется с _parent_store, позволяет быстрее обращаться к древовидной структуре

parent_right

смотрите parent_left

Декораторы методов

Этот модуль предоставляет элементы для управления двумя разными стилями API, а именно «старым стилем» и «новым стилем».

В старом стиле такие параметры как курсор базы данных, идентификатор пользователя, словарь контекста и идентификаторы записи (обычно обозначаемые как cr, uid, context, ids) Передаются явным образом всем методам. В в новом стиле эти параметры скрыты в экземплярах модели данных, что придает ему более объектно-ориентированный вид.

Например, выражения:

model = self.pool.get(MODEL)
ids = model.search(cr, uid, DOMAIN, context=context)
for rec in model.browse(cr, uid, ids, context=context):
    print rec.name
model.write(cr, uid, ids, VALUES, context=context)

также может быть записано как:

env = Environment(cr, uid, context) # cr, uid, context wrapped in env
model = env[MODEL]                  # retrieve an instance of MODEL
recs = model.search(DOMAIN)         # search returns a recordset
for rec in recs:                    # iterate over the records
    print rec.name
recs.write(VALUES)                  # update all records in recs

Методы, написанные в "старом" стиле, автоматически оформляются, следуя некоторым эвристическим методам, основанным на именах параметров.

odoo.api.multi(method)[исходный код]

Задекорируйте метод в новом стиле, где self - НЗ. Этот метод обычно определяет операцию над записями. Таким способом:

@api.multi
def method(self, args):
    ...

может быть вызван как в старом, так и в новом стиле, например:

# recs = model.browse(cr, uid, ids, context)
recs.method(args)

model.method(cr, uid, ids, args, context=context)
odoo.api.model(method)[исходный код]

Задекорируйте метод в новом стиле, где self - НЗ, но его содержимое не релевантно, только модель данных. Таким способом:

@api.model
def method(self, args):
    ...

может быть вызван как в старом, так и в новом стиле, например:

# recs = model.browse(cr, uid, ids, context)
recs.method(args)

model.method(cr, uid, args, context=context)

Обратите внимание, что ids передаются в методы только в старом стиле.

odoo.api.depends(*args)[исходный код]

Возвращает декоратор, который задает зависимости полей для метода "compute" (для вычисляемых полей в новом стиле). Каждый аргумент должен быть строкой, состоящей из разделенных точками последовательностей имен полей:

pname = fields.Char(compute='_compute_pname')

@api.one
@api.depends('partner_id.name', 'partner_id.is_company')
def _compute_pname(self):
    if self.partner_id.is_company:
        self.pname = (self.partner_id.name or "").upper()
    else:
        self.pname = self.partner_id.name

В качестве аргумента можно передать одну функцию. В этом случае зависимости задаются вызовом функции поля модели данных.

odoo.api.constrains(*args)[исходный код]

Декорирует проверку ограничений. Каждый аргумент должен быть именем поля, используемым для проверки:

@api.one
@api.constrains('name', 'description')
def _check_description(self):
    if self.name == self.description:
        raise ValidationError("Fields name and description must be different")

Вызывается для записей в новом стиле, в которых одно из именованных полей было изменено.

Должен быть вызван класс ValidationError, если проверка не прошла.

odoo.api.onchange(*args)[исходный код]

Возвращает декоратор, чтобы задекорировать метод onchange для заданных полей. Каждый аргумент должен быть именем поля:

@api.onchange('partner_id')
def _onchange_partner(self):
    self.message = "Dear %s" % (self.partner_id.name or "")

В представлении в виде формы где появляется поле, метод вызывается, когда одно из заданных полей изменяется. Метод вызывается в псевдо-записи, содержащей значения, присутствующие в форме. Назначения полей в этой записи автоматически отправляются обратно клиенту.

Метод может возвращать словарь для изменения полей домена и выводить предупреждающее сообщение, как в старом API:

return {
    'domain': {'other_id': [('partner_id', '=', partner_id)]},
    'warning': {'title': "Warning", 'message': "What is this?"},
}
odoo.api.returns(model, downgrade=None, upgrade=None)[исходный код]

Возвращает декоратор для методов, возвращающих экземпляры model.

Параметры
  • model -- наименование модели данных или 'self' для текущей модели данных
  • downgrade -- функция downgrade(self, value, *args, **kwargs) для преобразования нового стиля value в старый
  • upgrade -- функция upgrade(self, value, *args, **kwargs) для преобразования из старого стиля value в новый

Аргументы self, *args и kwargs - это параметры, которые передаются методу в новом стиле.

Декоратор приспосабливает вывод метода к стилю API: id, ids или False для старого стиля и НЗ для нового:

@model
@returns('res.partner')
def find_partner(self, arg):
    ...     # return some record

# output depends on call style: traditional vs record style
partner_id = model.find_partner(cr, uid, arg, context=context)

# recs = model.browse(cr, uid, ids, context)
partner_record = recs.find_partner(arg)

Обратите внимание, что декорированный метод должен удовлетворять этому соглашению.

Эти декораторы автоматически наследуются: метод, который переопределяет декорированный существующий метод, будет задекорирован тем же @returns(model).

odoo.api.one(method)[исходный код]

Задекорируйте метод нового стиля, где self должен быть ОЗ экземпляром. Декорированный метод автоматически перебирает записи и составляет список с результатами. Если метод задекорирован returns(), он складывает результирующие экземпляры. Таким способом:

@api.one
def method(self, args):
    return self.name

может быть вызван как в старом, так и в новом стиле, например:

# recs = model.browse(cr, uid, ids, context)
names = recs.method(args)

names = model.method(cr, uid, ids, args, context=context)

Не рекомендуется, начиная с версии 9.0: one() часто делает код менее понятным и ведет себя так, как могут не ожидать разработчики и читатели.

Настоятельно рекомендуется использовать multi() и либо выполнить итерацию по НЗ через self, либо убедиться, что НЗ является одной записью с ensure_one().

odoo.api.v7(method_v7)[исходный код]

Задекорируйте метод, который поддерживает только api в старом стиле. Новый API-интерфейс может быть предоставлен переопределением метода с тем же именем и декоратором v8():

@api.v7
def foo(self, cr, uid, ids, context=None):
    ...

@api.v8
def foo(self):
    ...

Особую осторожность следует проявлять, если один метод вызывает другой, потому что метод может быть переопределен! В этом случае следует вызвать метод из текущего класса (скажем, MyClass), например

@api.v7
def foo(self, cr, uid, ids, context=None):
    # Beware: records.foo() may call an overriding of foo()
    records = self.browse(cr, uid, ids, context)
    return MyClass.foo(records)

Обратите внимание, что метод-враппер использует docstring первого метода.

odoo.api.v8(method_v8)[исходный код]

Задекорируйте метод, который поддерживает только API-интерфейс нового стиля. Для api старого стиля можно переопределить метод с тем же именем и задекорировать его v7():

@api.v8
def foo(self):
    ...

@api.v7
def foo(self, cr, uid, ids, context=None):
    ...

Обратите внимание, что метод-враппер использует docstring первого метода.

Поля

Основные поля

class odoo.fields.Field(string=<object object>, **kwargs)[исходный код]

Дескриптор поля содержит определение поля и управляет доступом и присвоением соответствующего поля для записей. При инициализации поля могут быть предоставлены следующие атрибуты:

Параметры
  • string -- Метка поля, видимая пользователями (строка); Если не установлено, ORM берет имя поля в классе (с заглавной буквы).
  • help -- Всплывающая подсказка поля, видимая пользователями (строка)
  • readonly -- Является ли поле readonly (логическим, по умолчанию `` False``)
  • required -- Требуется ли значение поля (логическое значение, по умолчанию `` Ложное_`)
  • index -- Является ли поле индексированным в базе данных (логическое, по умолчанию `` Ложное``)
  • default -- Значение по умолчанию для поля; Это либо статическое значение, либо функция, выполняющая набор записей и возвращающая значение; Используйте `` default = None``, чтобы сбросить значения по умолчанию для поля
  • states -- Словарь значений состояния отображения в списки пар атрибут-значение пользовательского интерфейса; Возможные атрибуты: «readonly», «required», «invisible». Примечание. Любое состояние на основе состояния требует, чтобы в пользовательском интерфейсе клиентской стороны было доступно значение поля `` состояние``. Обычно это делается путем включения его в соответствующие представления, возможно сделанные невидимыми, если это не относится к конечному пользователю.
  • groups -- Список групповых xml-идентификаторов (строка), разделённых запятыми; Это ограничивает доступ к полям только для пользователей указанных групп
  • copy (bool) -- Следует ли копировать значение поля при дублировании записи (по умолчанию: `` True`` для обычных полей, `` False`` для `` one2many`` и вычисляемых полей, включая поля свойств и связанные поля)
  • oldname (string) -- Предыдущее имя этого поля, чтобы ORM мог автоматически переименовать его при миграции

Вычисляемые поля

Можно определить поле, значение которого вычисляется вместо простого чтения из базы данных. Атрибуты, специфичные для вычисляемых полей, приведены ниже. Чтобы определить такое поле, просто укажите значение атрибута `` compute``.

Параметры
  • compute -- Имя метода, который вычисляет поле
  • inverse -- Имя метода, который инвертирует поле (необязательно)
  • search -- Имя метода, реализующего поиск по полю (необязательно)
  • store -- Хранится ли поле в базе данных (логическое значение, по умолчанию `` Ложное`` в вычисленных полях)
  • compute_sudo -- Должно ли поле быть пересчитано в качестве суперпользователя для обхода прав доступа (логическое, по умолчанию `` False``)

Методы, приведенные для `` compute``, `` inverse`` и `` search``, являются модельными методами. Их подпись показана в следующем примере

upper = fields.Char(compute='_compute_upper',
                    inverse='_inverse_upper',
                    search='_search_upper')

@api.depends('name')
def _compute_upper(self):
    for rec in self:
        rec.upper = rec.name.upper() if rec.name else False

def _inverse_upper(self):
    for rec in self:
        rec.name = rec.upper.lower() if rec.upper else False

def _search_upper(self, operator, value):
    if operator == 'like':
        operator = 'ilike'
    return [('name', operator, value)]

Метод compute должен назначить поле для всех записей набора записей. Декоратор: meth: [UNKNOWN NODE title_reference] должен быть применен к методу compute для указания зависимостей полей; Эти зависимости используются, чтобы определить, когда нужно пересчитывать поле; Пересчет является автоматическим и гарантирует согласованность кэша / базы данных. Обратите внимание, что один и тот же метод может использоваться для нескольких полей, вам просто нужно назначить все указанные поля в методе; Метод будет вызываться один раз для всех этих полей.

По умолчанию вычисленное поле не сохраняется в базе данных и вычисляется «на лету». Добавление атрибута `` store = True`` будет хранить значения поля в базе данных. Преимущество хранимого поля в том, что поиск по этому полю выполняется самой базой данных. Недостатком является то, что для обновления необходимо обновить базу данных.

Обратный метод, как следует из его имени, делает инверсию метода compute: вызванные записи имеют значение для поля, и вы должны применять необходимые изменения для зависимостей полей, чтобы вычисление давало ожидаемое значение. Обратите внимание, что вычисляемое поле без обратного метода по умолчанию доступно только для чтения.

Метод поиска вызывается при обработке доменов перед выполнением фактического поиска по модели. Он должен возвращать домен, эквивалентный условию: `` значение оператора поля``.

Значение связанного поля задается последовательностью реляционных полей и чтением поля по достигнутой модели. Полная последовательность полей для перемещения определяется атрибутом

Параметры
related -- Последовательность имен полей

Некоторые атрибуты полей автоматически копируются из исходного поля, если они не переопределены: `` строка``, `` help``, `` readonly``, `` required`` (только если все поля в последовательности обязательны) , `` Группы``, [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference],` [UNKNOWN NODE title_reference]. Все семантически-свободные атрибуты копируются из исходного поля.

По умолчанию значения связанных полей не сохраняются в базе данных. Добавьте атрибут `` store = True``, чтобы он сохранялся, как и вычисляемые поля. Связанные поля автоматически пересчитываются при изменении их зависимостей.

Зависимые от компании поля

Ранее известные как поля свойств, значение этих полей зависит от компании. Другими словами, пользователи, принадлежащие к разным компаниям, могут видеть разные значения поля для данной записи.

Параметры
company_dependent -- Является ли поле зависимым от компании (булево)

Разреженные поля

Разреженные поля имеют очень малую вероятность того, что они не являются нулевыми. Поэтому многие такие поля могут быть сериализованы компактно в общее место, причем последнее является так называемым «сериализованным» полем.

Параметры
sparse -- Имя поля, в котором должно храниться значение этого поля.

Пошаговое определение

Поле определяется как атрибут класса в классе модели. Если модель расширена (см.: Класс: [UNKNOWN NODE title_reference]), можно также расширить определение поля, переопределив поле под тем же именем и тем же типом в подклассе. В этом случае атрибуты поля берутся из родительского класса и переопределяются атрибутами, указанными в подклассах.

Например, второй класс ниже только добавляет всплывающую подсказку в поле `` state``

class First(models.Model):
    _name = 'foo'
    state = fields.Selection([...], required=True)

class Second(models.Model):
    _inherit = 'foo'
    state = fields.Selection(help="Blah blah blah")
class odoo.fields.Char(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Поле основной строки может быть ограничено по длине, обычно отображается в виде строки с одной строкой в ​​клиентах.

Параметры
  • size (int) -- Максимальный размер значений, хранящихся для этого поля
  • translate -- Включить перевод значений поля; Используйте `` translate = True`` для перевода значений полей в целом; `` Translate`` также может быть вызываемым, так что [UNKNOWN NODE title_reference] [UNKNOWN NODE title_reference] [UNKNOWN NODE title_reference] с помощью` [UNKNOWN NODE title_reference] [UNKNOWN NODE problematic], чтобы получить перевод терминов.
class odoo.fields.Boolean(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

class odoo.fields.Integer(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

class odoo.fields.Float(string=<object object>, digits=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Цифры точности задаются атрибутом

Параметры
digits -- Пара (total, decimal) или функция, берущая курсор базы данных и возвращающая пару (total, decimal)
class odoo.fields.Text(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Очень похоже на: class: [UNKNOWN NODE title_reference], но используется для более длинного содержимого, не имеет размера и обычно отображается как многострочное текстовое поле.

Параметры
translate -- Включить перевод значений поля; Используйте `` translate = True`` для перевода значений полей в целом; `` Translate`` также может быть вызываемым, так что [UNKNOWN NODE title_reference] [UNKNOWN NODE title_reference] [UNKNOWN NODE title_reference] с помощью` [UNKNOWN NODE title_reference] [UNKNOWN NODE problematic], чтобы получить перевод терминов.
class odoo.fields.Selection(selection=<object object>, string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Параметры
  • selection -- Указывает возможные значения для этого поля. Он задается либо как список пар («значение», «строка»), либо как модельный метод, либо как имя метода.
  • selection_add -- Предоставляет расширение выбора в случае переопределенного поля. Это список пар (`` значение``, `` строка``).

Атрибут `` selection`` является обязательным, за исключением случая: ref: [UNKNOWN NODE title_reference] или: ref: [UNKNOWN NODE title_reference].

class odoo.fields.Html(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

class odoo.fields.Date(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

static context_today(record, timestamp=None)[исходный код]

Возвращает текущую дату в часовом поясе клиента в формате, соответствующем полям даты. Этот метод может использоваться для вычисления значений по умолчанию.

Параметры
timestamp (datetime) -- Необязательное значение datetime для использования вместо текущей даты и времени (должно быть datetime, регулярные даты не могут быть преобразованы между часовыми поясами).
Тип результата
static from_string(value)[исходный код]

Преобразуйте значение ORM `` значение`` в значение: class: [UNKNOWN NODE title_reference].

static to_string(value)[исходный код]

Преобразовать a: class: значение [UNKNOWN NODE title_reference] в формат, ожидаемый ORM.

static today(*args)[исходный код]

Возвращает текущий день в формате, ожидаемом ORM. Эта функция может использоваться для вычисления значений по умолчанию.

class odoo.fields.Datetime(string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

static context_timestamp(record, timestamp)[исходный код]

Возвращает заданную временную метку, преобразованную в часовой пояс клиента. Этот метод * не * предназначен для использования в качестве инициализатора по умолчанию, поскольку поля даты и времени автоматически преобразуются при отображении на стороне клиента. Для значений по умолчанию: meth: [UNKNOWN NODE title_reference] следует использовать вместо этого.

Параметры
timestamp (datetime) -- Наивное значение даты и времени (выраженное в формате UTC), которое должно быть преобразовано в часовой пояс клиента
Тип результата
Результат
Временная метка, преобразованная в datetime с учетом часового пояса в контексте часового пояса
static from_string(value)[исходный код]

Преобразуйте значение ORM в значение: class: [UNKNOWN NODE title_reference].

static now(*args)[исходный код]

Возвращает текущий день и время в формате, ожидаемом ORM. Эта функция может использоваться для вычисления значений по умолчанию.

static to_string(value)[исходный код]

Преобразуйте значение типа: datetime в формат, ожидаемый ORM.

Реляционные поля

class odoo.fields.Many2one(comodel_name=<object object>, string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Значение такого поля - это набор записей размера 0 (нет записи) или 1 (одна запись).

Параметры
  • comodel_name -- Имя целевой модели (строка)
  • domain -- Необязательный домен для установки значений кандидатов на стороне клиента (домен или строка)
  • context -- Необязательный контекст для использования на стороне клиента при обработке этого поля (словаря)
  • ondelete -- Что делать, если упомянутая запись удалена; Возможные значения: `` 'set null```, ' restrict', `` 'cascade'[UNKNOWN NODE problematic][UNKNOWN NODE problematic]
  • auto_join -- Генерируются ли JOIN при поиске в этом поле (логическое значение, по умолчанию `` False``)
  • delegate -- Установите его в `` True``, чтобы сделать поля целевой модели доступными из текущей модели (соответствует `` _inherits``)

Атрибут `` comodel_name`` является обязательным, за исключением случаев, касающихся связанных полей или расширений полей.

class odoo.fields.One2many(comodel_name=<object object>, inverse_name=<object object>, string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Поле One2many; Значение такого поля является набором записей всех записей в `` comodel_name``, так что поле `` inverse_name`` равно текущей записи.

Параметры
  • comodel_name -- Имя целевой модели (строка)
  • inverse_name -- Имя инверсного поля `` Many2one`` в `` comodel_name`` (строка)
  • domain -- Необязательный домен для установки значений кандидатов на стороне клиента (домен или строка)
  • context -- Необязательный контекст для использования на стороне клиента при обработке этого поля (словаря)
  • auto_join -- Генерируются ли JOIN при поиске в этом поле (логическое значение, по умолчанию `` False``)
  • limit -- Необязательное ограничение на чтение (целое)

Атрибуты `` comodel_name`` и `` inverse_name`` обязательны, за исключением соответствующих полей или расширений полей.

class odoo.fields.Many2many(comodel_name=<object object>, relation=<object object>, column1=<object object>, column2=<object object>, string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Поле Many2many; Значением такого поля является набор записей.

Параметры
comodel_name -- Имя целевой модели (строка)

Атрибут `` comodel_name`` является обязательным, за исключением случаев, касающихся связанных полей или расширений полей.

Параметры
  • relation -- Необязательное имя таблицы, в которой хранится отношение в базе данных (строка)
  • column1 -- Необязательное имя столбца, ссылающееся на "эти" записи в таблице relation (строка)
  • column2 -- Необязательное имя столбца, ссылающегося на "те" записи в таблице relation (строка)

Атрибуты `` отношение``, `` column1`` и `` column2`` являются необязательными. Если не указано, имена автоматически генерируются из имен моделей, если [UNKNOWN NODE title_reference] и` [UNKNOWN NODE title_reference] различны!

Параметры
  • domain -- Необязательный домен для установки значений кандидатов на стороне клиента (домен или строка)
  • context -- Необязательный контекст для использования на стороне клиента при обработке этого поля (словаря)
  • limit -- Необязательное ограничение на чтение (целое)
class odoo.fields.Reference(selection=<object object>, string=<object object>, **kwargs)[исходный код]

Базовые классы:: class: [UNKNOWN NODE title_reference]

Наследование и расширение

Odoo обеспечивает три различных механизма для расширения моделей данных по модульному принципу:

  • создание новой модели данных из уже существующей, добавляя новую информацию в копию, но оставляя исходный модуль как есть

  • расширение моделей данных, определенных в других модулях, заменяя предыдующую версию

  • делегировании некоторых полей моделей данных к записям, которые они содержат

Классическое наследование

При использовании атрибутов _inherit и _name вместе, Odoo создает новую модель, используя уже существующую (с помощью атрибута : attr: [UNKNOWN NODE title_reference]) в качестве базиса. Новая модель получает все поля, методы и мета-информацию (defaults & al) от базисной модели данных.


class Inheritance0(models.Model):
    _name = 'inheritance.0'

    name = fields.Char()

    def call(self):
        return self.check("model 0")

    def check(self, s):
        return "This is {} record {}".format(s, self.name)

class Inheritance1(models.Model):
    _name = 'inheritance.1'
    _inherit = 'inheritance.0'

    def call(self):
        return self.check("model 1")

и их использование:

        a = env['inheritance.0'].create({'name': 'A'})
        b = env['inheritance.1'].create({'name': 'B'})
            a.call()
            b.call()

даст следующий результат:

            "This is model 0 record A"
            "This is model 1 record B"

вторая модель данных унаследовала от первой метод проверки check и ее поле name, но переопределила метод call, как при использовании стандартного механизма наследования Python.

Расширение

При использовании _inherit, но не учитывая _name, новая модель данных заменит собой уже существующую, расширяя ее. Это полезно для добавления новых полей или методов в существующие модели данных (созданные в других модулях), или их индивидуальной настройки (например, чтобы изменить их порядок сортировки по умолчанию):


class Extension0(models.Model):
    _name = 'extension.0'

    name = fields.Char(default="A")

class Extension1(models.Model):
    _inherit = 'extension.0'

    description = fields.Char(default="Extended")
        env = self.env
        {'name': "A", 'description': "Extended"}

даст следующий результат:


Делегирование

Третий механизм наследования обеспечивает большую гибкость (существует возможность изменения во врмемя выполнения) но требует больше мощностей: использу _inherits модель данных делегирует поиск любого поля, не найденного в текущей модели данных "дочерним" моделям данных. Делегирование осуществляется с помощью Reference, полей автомтически установленных на родительской модели данных:


class Child0(models.Model):
    _name = 'delegation.child0'

    field_0 = fields.Integer()

class Child1(models.Model):
    _name = 'delegation.child1'

    field_1 = fields.Integer()

class Delegating(models.Model):
    _name = 'delegation.parent'

    _inherits = {
        'delegation.child0': 'child0_id',
        'delegation.child1': 'child1_id',
    }

    child0_id = fields.Many2one('delegation.child0', required=True, ondelete='cascade')
    child1_id = fields.Many2one('delegation.child1', required=True, ondelete='cascade')
        record = env['delegation.parent'].create({
            'child0_id': env['delegation.child0'].create({'field_0': 0}).id,
            'child1_id': env['delegation.child1'].create({'field_1': 1}).id,
        })
            record.field_0
            record.field_1

даст результат:

            0
            1

есть возможность сделать запись прямо в делегированное поле:

        record.write({'field_1': 4})

Домены

Домен - это список критериев, каждый критерий состоит из трех частей ( является либо списком или кортежем) (имя_поля, оператор, значние) где:

имя_поля (str)

имя поля текущей модели или отношение через класс Many2one с использованием dot-нотации, например 'street' или 'partner_id.country'

operator (str)

оператор, используемый для сравнения имя_поля со значением. Допустимые операторы:

=

равно

!=

не равно

>

больше чем

>=

больше чем или равно

<

меньше чем

<=

меньше чем или равно

=?

не задано или равно (возварщает true если значение является либо``None`` или False, в противном случае ведет себя как =)

=like

сопоставляет имя_поля с шаблоном значения. Подчеркивание _ в шаблоне означает (соответствует) любому одиночному символу; знак процента % соответствует любой строке из нуля или более символов.

like

сопоставляет имя_поля с шаблоном %значения%. Так же как =like, но оборачивает значение в % перед сравнением

not like

не сопоставляет с шаблоном %value%

ilike

не чувтсвительный к регистру like

not ilike

не чувствительный к регистру not like

=ilike

не чувтсвительный к регистру =like

in

равно любому из элементов значения, `` значение`` должно быть списком элементов

not in

не равно любому из элементов значения

child_of

дочернее значение (потомок) value записи.

Принимает во внимание семантику модели данных (т. е. за следующий реляционным полем , с наименованием _parent_name).

value

тип переменной, который должен быть сопоставим (через operator) с названным полем

Критерии домена могут быть объединены с помощью логических операторов в виде prefix:

'&'

логическое И, операция по умолчанию для объединения критериев, следующих друг за другом. Arity 2 (испольузет следующие 2 кртерия или комбинации).

'|'

логическое ИЛИ, arity 2.

'!'

Логическое НЕ, arity 1.

Портирование со старого API на новый API

  • в новом API необходимо исключить списки идентификаторов, вместо этого использовать НЗ

  • методы, все еще написанные на старом API, должны автоматически работать с ORM, отсутствует необходимость переключения на старый API, просто вызывайте их, как если бы они были методом нового API. Смотрите Автоматический проброс старых API-методов для более подробной информации.

  • search() возвращает НЗ, не имеет смысла, например, при просмотре его результата

  • fields.related и fields.function заменяются с использованием нормального типа поля с параметром related= или compute=

  • функции depends() в compute= методах должны быть полными, они должны отобразить все поляполя, которые использует метод для вычисления. Лучше иметь слишком много зависимостей (будет пересчитывать поле в тех случаях, когда это не требуется), чем недостаточное их количество (забудет пересчитать поле, в следствии чего значения будут неверны)

  • удалить все методы onchange для вычисляемых полей. Вычисляемые поля автоматически пересчитываются при изменении значения одного из полей, указанных в зависимостях и используются для автоматической генерации onchange клиентом

  • декораторы model() и multi() предназначены для объединения при вызове из контекста старого API, для внутренних или простых методов нового API (например, compute) они бесполезны

  • замените _default, замените параметром default= в соответствующих полях

  • если параметр поля string= - это наименование поля с большой буквы:

    name = fields.Char(string="Name")
    

    он бесполезен и должен быть удален

  • параметр multi= ничего не делает в полях в новом API, он использует одни и те же методы что и compute= во всех соответствующих полях для достижения одного и того же результата

  • предоставляет compute=, inverse= и search= методы по имени (как строку), это делает их переопределяемыми (устраняет необходимость в промежуточной функции "трамплине")

  • дважды проверьте, что все поля и методы имеют разные имена, в случае совпадения их имен предупреждение будет отсутствовать (поскольку Python обрабатывает его до того, как Odoo увидит что-либо)

  • нормальный импорт для нового API from odoo import fields, models. Если необходимы декораторы совместимости, используйте from odoo import api, fields, models.

  • избегайте one() декоратор, он, вероятно, не делает то, что вы ожидаете

  • Удалите явное определение полей create_uid, create_date, write_uid и write_date: они теперь создаются как обычные "законные" поля и могут читаться и записываться, как и любые другие

  • когда прямое преобразование невозможно (семантика не может быть преобразована), или версия «старого API» нежелательна и может быть улучшена до нового API, можно использовать совершенно разные «старые API» и «новые API» для одного и того же имени метода, используя v8(). Метод должен быть сначала определен с использованием старого API и задекорирован v7(), затем он должен быть переопределен с использованием того же самого имени, но с новым API-интерфейсом и задекорирован v8(). Вызовы из старого API-интерфейса будут отправлены в первую реализацию, а вызовы из контекста нового API будут отправлены во вторую реализацию. Одна реализация может вызывать (и часто делает) оба вызова, переключая контекст.

  • использование _columns or _all_columns следует заменить на by _fields, которые предоставляют доступ экземплярам с новым API odoo.fields.Field (чаще чем odoo.osv.fields._column).

    Не сохраненные вычисленные поля, созданные с использованием нового API, недоступны в _columns и могут быть проверены только через _fields

  • переназначение self в методе, вероятно, не нужно и может нарушить интроспекцию трансляции

  • manage при попытке использовать новый API в контекстах, где он еще не был настроен, например, новые потоки или интерактивная среда Python:

    >>> from odoo import api, modules
    >>> r = modules.registry.RegistryManager.get('test')
    >>> cr = r.cursor()
    >>> env = api.Environment(cr, 1, {})
    Traceback (most recent call last):
      ...
    AttributeError: environments
    >>> with api.Environment.manage():
    ...     env = api.Environment(cr, 1, {})
    ...     print env['res.partner'].browse(1)
    ...
    res.partner(1,)
    

Автоматический проброс старых API-методов

Когда модели инициализируются, все методы автоматически сканируются и пробрасываются, если они похожи на модели данных, объявленные в старом API. Этот проброс делает их прозрачно вызываемыми из методов нового API.

Методы сопоставляются как «старый-API», если их второй позиционный параметр (после self) называется cr или cursor. Система также распознает третий позиционный параметр, называемый uid или user, а четвертый называется id или ids. Он также распознает наличие любого параметра, вызываемого с помощью context.

При вызове таких методов из контекста нового API система автоматически заполнит согласованные параметры из текущего Environment (for cr, user and context) или текущий НЗ (для id and ids).

В редких случаях, когда это необходимо, проброс можно настроить, задекорировав метод старого API:

  • полностью отключить его, задекорировав метод с помощью noguess() не будет никакого проброса, и методы будут вызываться точно таким же образом из нового и старого API

  • явным образом определяя проброс, это в основном подходит для методов, которые неправильно сопоставляются (потому что параметры названы непредвиденными способами):

    cr()

    автоматически добавит текущий курсор к явно заданным параметрам, позиционно

    cr_uid()

    автоматически добавит текущий курсор и идентификатор пользователя к явно заданным параметрам

    cr_uid_ids()

    автоматически добавит текущий курсор, идентификатор пользователя и идентификаторы набора записей в явно заданные параметры

    cr_uid_id()

    будет выполнять перебор по текущему набору записей и вызывать метод один раз для каждой записи, добавляя к текущему курсору, идентификатору пользователя и идентификатору записи явно указанные параметры.

    Все эти методы имеют версию _context-suffixed (например cr_uid_context()), которая также передает текущий контекст по ключевому слову.

  • двойная реализация, использующая v7() и v8() будет игнорироваться, поскольку они предоставляют свои собственные "пробросы"