Краткое описание обучения ODM API и учебное пособие по ORM
Краткое описание обучения ODM API и учебное пособие по ORM

среда

odoo-14.0.post20221212.tar

Краткое описание обучения/учебное пособие по ORM API

Модель

Поля модели определяются как свойства самой модели.

Язык кода:javascript
копировать
from odoo import models, fields
class AModel(models.Model):
    _name = 'a.model.name'

    field1 = fields.Char()

предупреждать Имя поля и имя метода не могут совпадать. Последнее определенное имя метода и функции перезапишет то же имя, определенное ранее.

По умолчанию метка поля (Lable, то есть видимое пользователю имя поля) — это значение после того, как начальные буквы соответствующего имени поля будут изменены на прописные. Можно передать. string Измените атрибут поля, чтобы изменить метку поля.

Язык кода:javascript
копировать
field2 = fields.Integer(string="Field Label")

Сносноdefault,Определить цену по умолчанию:

Язык кода:javascript
копировать
name = fields.Char(default="a value")

Значения по умолчанию также можно получить через функции:

Язык кода:javascript
копировать
    def _default_name(self):
        return 'Title'

name = fields.Char(default=lambda self: self._default_name())
API
BaseModel

class odoo.models.BaseModel[исходный код]

Базовый класс для моделей Odoo. Режим Odoo может создавать модель, наследуя следующие классы:

  • Model Для общей модели персистентности базы данных
  • TransientModel Используется для временных данных, хранящихся в базе данных, но время от времени автоматически удаляемых.
  • AbstractModel Абстрактный родительский класс для совместного использования нескольких наследуемых модулей, не создает таблицы моделей в базе данных.

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

Каждый экземпляр модели представляет собой «набор записей», упорядоченный набор записей модели. Набор записей состоит из browse(), search()или Доступ к полям и методам появились. Записи не имеют явного представления: одна запись представляет собой набор записей из одной записи.

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

_auto= False

Следует ли создавать таблицу базы данных. Если установлено значение False, следует переписать init()создать таблицу базы данных。Настройка по умолчанию。противModelиTransientModelАвтоматически устанавливаетсядляFalse,противAbstractModelАвтоматически устанавливаетсядляFalse。Сносно继承AbstractModelсоздать тот, который не требует каких-либо таблиц данных Модель

_log_access

Будет ли ORM автоматически генерировать и обновлять Access Log fields。по умолчанию_autoизценить。

_table= None

Модельверноотвечатьиз数据库поверхностьизимя。если_autoнастраиватьдляTrueиз话。

_sequence= None

Последовательность SQL для поля идентификатора

_sql_constraints= []

ограничения SQL,Формат:[(name, sql_def, message)]

_register= True

registry visibility

_abstract= True

Будь то абстрактная модель

_transient= False

лидляtransientМодель

_name= None

Название модели (начинается с точкаточка式имяиз模块имя,напримерestate.users

_description= None

Описание модуля, нецелое имя

_inherit= None

унаследованныйPythonМодель:Нужно наследовать Модельизимя(_nameсвойствоценить)илисписок имен(listтип)

_inherits= {}(Не совсем понимаю)

dictionary {‘parent_model’: ‘m2o_field’} mapping the _name of the parent business objects to the names of the corresponding foreign key fields to use:

Язык кода:javascript
копировать
_inherits = {
    'a.model': 'a_field_id',
    'b.model': 'b_field_id'
}

implements composition-based inheritance: the new model exposes all the fields of the inherited models but stores none of them: the values themselves remain stored on the linked record.

предупреждать

if multiple fields with the same name are defined in the _inherits-ed models, the inherited field will correspond to the last one (in the inherits list order).

_rec_name= None

Поле для разметки записей,по умолчаниюценить:name

_order= 'id'

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

_check_company_auto= False

осуществлятьwrite иcreate, обладать check_company=Trueсвойствоизассоциация Полевызов_check_company чтобы обеспечить целостность компании

_parent_name= 'parent_id'

Поле «many2one», используемое в качестве родительского поля

_parent_store= False

настраиватьдляTrueрассчитатьparent_pathПоле。иparent_path вместе,Настройте индексное хранилище для древовидной структуры записей.,так чтоиспользоватьchild_ofиparent_ofОператоры домена применяются к текущему Модельиз Записывать进行更快източказапрос слоя

_date_name= 'date'

Поля, используемые для просмотра календаря по умолчанию

_fold_name= 'fold'

Поле, используемое для определения свернутых групп в представлении Канбан.

AbstractModel

odoo.models.AbstractModel[исходный код]

odoo.models.BaseModelиз别имя

Model

class odoo.models.Model[исходный код]

Основной родительский класс для обычных моделей персистентности базы данных Odoo.

Создайте модели Odoo, унаследовав этот класс:

Язык кода:javascript
копировать
class user(Model):
    ...

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

  • _auto= True Следует ли создавать таблицу базы данных. Если установлено значение False, следует переписать init()создать таблицу базы данных。Настройка по умолчанию。противModelиTransientModelАвтоматически устанавливаетсядляFalse,противAbstractModelАвтоматически устанавливаетсядляFalse。Сносно继承AbstractModelсоздать тот, который не требует каких-либо таблиц данных Модель
  • _abstract= False Будь то абстрактная модель
  • _transient= False лидляtransientМодель
TransientModel

class odoo.models.TransientModel[исходный код]

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

TransientModel具иметь简化издоступ权限管理,Все пользователи могут создаватьновый записывать и получать к ним доступ только записи созданы。Суперпользователь имеет неограниченный доступ ко всемTransientModelЗаписывать。

  • _auto= True Следует ли создавать таблицу базы данных. Если установлено значение False, следует переписать init()создать таблицу базы данных。Настройка по умолчанию。противModelиTransientModelАвтоматически устанавливаетсядляFalse,противAbstractModelАвтоматически устанавливаетсядляFalse。Сносно继承AbstractModelсоздать тот, который не требует каких-либо таблиц данных Модель
  • _abstract= False Будь то абстрактная модель
  • _transient= False лидляtransientМодель

Поля

class odoo.fields.Field[исходный код]

Поля имеют следующие свойства

string (str) – Метка поля, которую видит пользователь; если она не установлена, ORM будет использовать первую букву имени поля в классе, которая будет заглавной.

help (str) – Панель подсказок поля, которую видит пользователь (после установки этого атрибута при наведении курсора мыши на метку поля автоматически появляется панель подсказок для отображения текстового содержимого атрибута).

invisible – Полели可见。по умолчаниюдляFalse,Видимый

readonly (bool) – Доступно ли поле только для чтения в пользовательском интерфейсе, значение по умолчанию. False,Работает только в пользовательском интерфейсе

required (bool) – Требуется ли поле в пользовательском интерфейсе, по умолчанию False。Это делается на уровне базы данныхдля Столбец добавленNOT NULL ограничения для достижения

index (bool) – Добавлять ли индекс в поле. Примечание. Это не работает для несохраненных и виртуальных полей. значение по умолчанию: False

default (значение или вызываемый объект) – Установите значение поля по умолчанию. Это может быть статическое значение или функция, которая принимает набор результатов в качестве входного параметра и возвращает определенное значение. использовать default=Noneотбрось это Полеизпо умолчаниюценить。

states (dict) –Воляstateценитьсопоставлено сUIсвойство-ценитьверносписокизсловарь映射,Проще говоря, он позволяет создавать пользовательский интерфейс на основеstateПолеизценить Приходить动态настраиватьверноотвечать ПолеизUIсвойство,поэтому,Для этого требуется наличиеstateПолеи в представлениииспользовать(即使да隐藏из),stateсвойствоизимядасуществоватьodoo硬编码и Нет允许修改из,可用свойствоиметь: readonly, required, invisible。Напримерstates={'done':[('readonly',True)]},означает, когдаstateценитьдляdoneчас,Воляпользовательский интерфейсstatesрасположение Полесуществоватьнастраиватьдлятолько чтение (только для уровня пользовательского интерфейса)

Примеры использования:

Язык кода:javascript
копировать
state = fields.Selection([
        ('draft', 'To Submit'),
        ('cancel', 'Cancelled'),
        ('confirm', 'To Approve'),
        ('refuse', 'Refused'),
        ('validate1', 'Second Approval'),
        ('validate', 'Approved')
        ], string='Status', readonly=True, copy=False, default='confirm')
date_from = fields.Datetime(
        'Start Date', readonly=True, index=True, copy=False,
        states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})

groups (str) – Значения представляют собой группы XML, разделенные запятыми. список идентификаторов,нравитьсяgroups='base.group_user,base.group_system',Доступ к Поле может быть ограничен только для пользователей определенной группы.

company_dependent (bool) –

Зависит ли Полеценить от текущей компании?,еслинастраиватьдляTrue,означает полагаться на текущую компанию,Это является обязательным условием компании «Полеценитьи». Функция этого атрибута – сделать такого же Поле, может основываться не на таком та же компания, склад не такой жеценить, если предположить, что пользователь принадлежит более чем к одной компании, он не такой же公司из职务也Нетодин样,此час就可кнастраивать ДолженсвойстводляTrue

Долженценитьне хранится в текущем Модельв таблице。он регистрируетсядляir.property,也就да说этоизценитьхранится вir_propertyв таблице,Получите цену поля, запросив таблицу.

copy (bool) – При дублировании записей копируется ли значение поля (при использовании ORM copy()методкопироватьи генерироватьновый рекордчас,Неткопировать Должен Полеизценить)。 (Для обычных полей значение по умолчанию: True ,противone2manyи Расчетное поле,包括свойство Поле(property fields,Регистрация личного взаимопониманияir.propertyиз Поле)исвязь Поле,по умолчаниюценитьдляFalse

store (bool) – Сохраняется ли Поле в базе данных для Расчетного поле,по умолчаниюценитьдляFalse,другой Полепо умолчаниюдляTrue

group_operator (str) –

При группировке по текущему полю для read_group() используемая агрегатная функция

Поддерживаемые агрегатные функции:

  • array_agg : ценить,Включить пустую цену,объединить в массив
  • count : Количество записей
  • count_distinct : Не повторяется записей
  • bool_and : для истинно, если все ценить истинно, в противном случае для ложно
  • bool_or : если至少иметьодинценитьдлянастоящий,нодлянастоящий,В противном случаедляfalse
  • max : Максимальная цена из всех цен
  • min : Минимальная цена из всех цен
  • avg : средняя цена всех цен (средняя арифметическая цена)
  • sum : Всего и всех ценить

group_expand (str) –

используется в настоящее время Поленачальствоточка Группачас用于Расширять read_group функция результата

Язык кода:javascript
копировать
@api.model
def _read_group_selection_field(self, values, domain, order):
    return ['choice1', 'choice2', ...] # available selection choices.

@api.model
def _read_group_many2one_field(self, records, domain, order):
    return records + self.search([custom_domain])
Основные поля
class odoo.fields.Boolean[исходный код]

boolиз封装

class odoo.fields.Char[исходный код]

Базовое строковое поле, ограниченное по длине, обычно отображается на клиенте как однострочная строка.

параметр:

  • size(int) – для Поле может хранить максимум ценить
  • trim(bool) – Указывает, сокращена ли цена (по умолчанию True)。пожалуйста Уведомление,черносливдействоватьтолько Web клиентское приложение.
  • translate(bool или вызываемый объект)– Включить перевод слова «Полеценить», используемого для;translate=TrueОбщий перевод Полеценить;translateтакже может быть вызываемым, что делаетtranslate(callback,value)проходитьиспользоватьcallback(term)искать перевод терминов для переводаvalue`
class odoo.fields.Float[исходный код]

floatиз封装

精度数字由Необязательныйизdigitalsсвойство Давать出。

параметр

digits (tuple(int, int), илиstr ) – одинкортеж(total, decimal) или ЦитироватьDecimalPrecision записанная строка

Язык кода:javascript
копировать
digits=(8,2) Представляет в общей сложности 8 цифр, а десятичная точка занимает 2 цифры.

Класс Float предоставляет для этого несколько статических методов:

round()к Давать定精度верно浮точкаценитьвыполнить округление。is_zero()检查浮точкаценитьсуществовать Давать定精度下лиравныйноль。compare()в соответствии с Давать定精度Сравниватьдва浮точкаценить。

пример:

Язык кода:javascript
копировать
fields.Float.round(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
Язык кода:javascript
копировать
fields.Float.is_zero(self.product_uom_qty, precision_rounding=self.product_uom_id.rounding)
Язык кода:javascript
копировать
field.Float.compare(self.product_uom_qty, self.qty_done, precision_rounding=self.product_uom_id.rounding)

Сравнивать助手出于历史目изиспользовать__cmp_Семантика,поэтомуиспользовать此助手из正确惯用Способследующее:

Если результат==0, первое и второе числа с плавающей запятой равны. Если результат<0, первое число с плавающей запятой равно меньше. чем Второй,еслиresult>0,第один浮动точка数больше, чем Второе число с плавающей запятой

class odoo.fields.Integer[исходный код]

intиз封装

Расширенные поля
class odoo.fields.Binary[исходный код]

Инкапсулировать двоичный контент (например, файл).

параметр:

  • attachment(bool)– Есть ли магазины Поле дляir_attachmentИли столбец таблицы модели (по умолчанию для:True`, то есть сохраняется прежнее.
class odoo.fields.Html[исходный код]

Инкапсуляция содержимого html-кода

параметр:немного

class odoo.fields.Image[исходный код]

Картинная упаковка,РасширятьBinary

Если размер изображения больше, чемкартина素изmax_width/max_heightпредел,Затем размер изображения подстраивается под этот предел, сохраняя соотношение сторон Воля.

параметр:

  • max_width(int ) – 图картинаизмаксимум宽度(по умолчаниюценить:0,без ограничений)
  • max_height ( int) – 图картинаизмаксимум高度(по умолчаниюценить:0,без ограничений)
  • verify_resolution ( bool) – лиотвечать验证图картинаточкаразрешениек确保это Нет会超过самое большое изображениеточкаразрешение(по умолчаниюценить:True。самое большое изображениеточкаразрешениепожалуйста参阅odoo.tools.image.ImageProcess(по умолчаниюценить:50e6)。 параметр

если не указано max_width/max_height илинастраиватьдля0,иverify_resolutionдляFalse,Поле контент не будет проверен,此часотвечать ДолжениспользоватьBinaryПоле。

class odoo.fields.Monetary[исходный код]

инкапсулирует данноеres_currencyповерхность示из浮точкаценить。

Десятичная точностьи Символ валюты взят изcurrency_fieldсвойство。

параметр:

  • currency_field (str) –拥иметьповерхность示Должен货币Полеизres_currency изMany2oneПолеимя(по умолчанию: 'currency_id')
class odoo.fields.Selection[исходный код]

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

проиллюстрировать:SelectionПолеиз Необязательныйценить,хранится вpublic.ir_model_fields_selectionв таблице,проходитьfield_idПолепроходитьpublic.ir_model_fieldsтаблица продолжить

Язык кода:javascript
копировать
-- QuerySelectionПолеID
SELECT id FROM public.ir_model_fields
where model = 'stock.quality' and name='state' 

-- Проверить выбор Поле Необязательноценить
select * from public.ir_model_fields_selection where field_id = 13028; -- 13028дляSelectionПолеID

параметр:

selection (list(tuple(str, str)) или вызываемый объект или str)) – обозначение Полеиз Необязательныйценить。Чтоценитьдля Включать2кортежизсписок,иливозвращаться прежним модельным методом,или Имя метода

selection_add (list(tuple(str, str)) –

В случае переписывания Поле,поставлятьselectionиз Расширять。этодаодин Включать二кортеж(value, label)илиодинкортеж(value,)изсписок,в,одинкортежсерединаизvalueДолжен сделатьдляvalueПоявиться вselectionсписоксерединаизкортежсередина。новыйценитьзаказ на размещениеиоригинальныйselectionсерединакортеж Следите за порядком:

Язык кода:javascript
копировать
selection = [('a', 'A'), ('b', 'B')]
selection_add = [('c', 'C'), ('b',)]
> result = [('a', 'A'), ('c', 'C'), ('b', 'B')]

ondelete

длясselection_addиз任何重写Полепоставлять回退机制。этотдаодин Воляselection_addсерединаизкаждый选项сопоставлено с回退действоватьизdict。

Этот запасной вариантдействовать Воляприложение于Чтоselection_add选项сопоставлено с Должендействоватьиз所иметь Записывать。

Это может быть любое из следующих действий:

  • set nullПо умолчанию,具иметь此选项из所иметь Записыватьизвыбиратьценить Все ВолянастраиватьдляFalse。
  • cascade–具иметь此选项из所иметь Записывать Воляи选项本身Вместеудалить.
  • set default-具иметь此选项из所иметь Записывать Все Волянастраиватьдля Полеопределениеизпо умолчаниюценить
  • <callable> -один可вызовобъект,Его первый и единственный параметр Воля — это набор записей, содержащий указанный параметр выбора.,для индивидуальной обработки

selectionсвойствовыбиратьда强制сексиз,Если это неrelatedили Расширятьиз Поле

class odoo.fields.Text[исходный код]

похожийChar,для более длинного контента,нет размера,обычно отображаетсядлянесколько строктексткоробка。

параметр:

translate (bool или вызываемый объект) – такой же Char

Поле даты (времени)

При присвоении значения Date/Datetime поле, допустимы следующие варианты:

  • date или datetime объект.
  • Правильно отформатированные символы:
    • DateПолеиспользоватьYYYY-MM-DD
    • DatetimeПолеиспользовать YYYY-MM-DD HH:MM:SS
  • False или None.

Date иDatetime Классы полей имеют следующие вспомогательные функции для попыток преобразования в совместимые типы:

Пример

Анализ даты/даты и времени из внешнего источника:

Язык кода:javascript
копировать
fields.Date.to_date(self._context.get('date_from'))

Date/Datetime Сравните лучшие практики:

  • DateПолеможет толькоиdateобъект Сравнивать
  • DatetimeПолеможет толькоиdatetimeобъект Сравнивать

Datetime Поля хранятся в базе данных как метки времени без часового пояса и в часовом поясе UTC. Это делает базу данных Odoo независимой от часового пояса системы хост-сервера. Преобразование часового пояса полностью управляется клиентом.

Common operations with dates and datetimes such as addition, subtraction or fetching the start/end of a period are exposed through both Date and Datetime. These helpers are also available by importing odoo.tools.date_utils.

class odoo.fields.Dateисходный код

Python dateобъектиз封装

static add(value, *args, **kwargs)

возвращаться value и relativedeltaИзи

  • параметр value – исходныйdateилиdatetime args – перешел кrelativedeltaиз Расположениепараметр kwargs – перешел кrelativedeltaиз关键词параметр
  • возвращаться date/datetimeрезультатобъект

Пример:

Язык кода:javascript
копировать
from odoo.fields import Date

print(Date.add(datetime.now(), years=1)) # Вывод выглядит так: 2024-01-03
# общийпараметр:
# years, months, days, leapdays, weeks, hours, minutes, seconds, microseconds

static subtract(value, *args, **kwargs)[исходный код]

возвращаться value и relativedeltaИз差

  • параметр value – исходныйdate илиdatetime args – перешел к relativedeltaРасположениепараметр kwargs – перешел к relativedeltaиз关键词параметр
  • возвращаться date/datetimeрезультатобъект

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

в соответствии с客户端час区к适合dateПолеиз Форматвозвращатьсятекущийдата

аннотация Этот метод можно использовать для расчета значения по умолчанию.

  • параметр record – Набор записей, из которого можно получить часовой пояс. timestamp (datetime) – 替代текущийдатачас间(datetime)из Необязательныйизdatetimeобъект
  • возвращатьсятип date

static end_of(value, granularity)[исходный код]

Получить конец периода времени по дате или дате и времени

  • параметр value – исходныйdate илиdatetime granularity – Тип периода времени, представленный строкой, может бытьyear, quarter, month, week, day илиhour
  • возвращаться иобозначениечас段из起始верноотвечатьизdate/datetimeобъект

Пример:

Язык кода:javascript
копировать
print(datetime.now()) # 2023-01-03 10:12:32.332208
print(Date.end_of(datetime.now(), 'year')) # Вывод выглядит так: 31 декабря 2023 г. 23:59:59.999999
print(Date.end_of(datetime.now(), 'month')) # Вывод выглядит так: 2023-01-31. 23:59:59.999999

static start_of(value, granularity)[исходный код]

Получить начало периода времени из даты или даты и времени.

  • параметр value – исходныйdate илиdatetime granularity – Тип периода времени, представленный строкой, может бытьyear, quarter, month, week, day илиhour
  • возвращаться иобозначениечас段из起始верноотвечатьизdate/datetimeобъект

Пример:

Язык кода:javascript
копировать
print(datetime.now()) # 2023-01-03 10:18:57.071276
print(Date.start_of(datetime.now(), 'year')) # Вывод выглядит так: 2023-01-01. 00:00:00
print(Date.start_of(datetime.now(), 'month')) # Вывод выглядит так: 2023-01-01. 00:00:00
print(Date.start_of(datetime.now(), 'hour')) # Вывод выглядит так: 2023-01-03 10:00:00

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

попробуй конвертировать value для date объект

предупреждать еслиvalueдляdatetimeобъект,это Воляодеяло Конвертировать дляdateобъект,и所иметьдатачас间特定信息(HMS, TZ, ...) будет потерян.

  • параметр value (str или date или datetime) — ценить то, что нужно конвертировать
  • возвращаться представлять valueизобъект
  • возвращатьсятип dateтипилиNone

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

Воля date илиdatetime объект для строки

  • параметр value – Объект даты или даты и времени, который необходимо преобразовать
  • возвращаться В формате даты сервера появляетсяпредставляет value нить. если value дляdatetimeтип,Автоматически сбрасывать часы,точка,Второй,Информация о часовом поясе.
  • возвращатьсятип:str

Пример:

Язык кода:javascript
копировать
print(Date.to_string(datetime.now())) # Вывод выглядит так: 2023-01-03

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

возвращатьсятекущийдата

Пример:

Язык кода:javascript
копировать
print(Date.today()) # Формат следующий: 03.01.2023.
class odoo.fields.Datetime[исходный код]

Python datetimeобъектиз封装

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

возвращаться Конвертировать для客户端час区из Давать定час间戳。

аннотация Этот метод не используется в качестве начальной настройки ценообразования по умолчанию.,потому чтодляdatetimeПолесуществовать客户端显示час会自动转换。дляпо умолчаниюценить,отвечатьиспользоватьnow()

  • параметр record – Набор записей, из которого можно получить часовой пояс.。 timestamp (datetime) – обращаться Конвертировать для客户端час区изnaive datetimeценить (UTCповерхность示из)
  • возвращаться в соответствии сначальство下文час区Конвертировать длячас区敏感изdatetime
  • возвращатьсятип datetime

static add(value, *args, **kwargs)[исходный код]

ссылкаDate.add

static subtract(value, *args, **kwargs)[исходный код]

ссылкаDate.subtract

static end_of(value, granularity)[исходный код]

ссылкаDate.end_of

static start_of(value, granularity)[исходный код]

ссылкаDate.start_of

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

ссылкаDate.to_string

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

возвращатьсяв тот день,полночь (00:00:00)

Пример:

Язык кода:javascript
копировать
from odoo.fields import Datetime

print(Datetime.today()) # Вывод выглядит так: 2023-01-03 00:00:00
print(Datetime.now()) # Вывод текущего времени 2023-01-03 12:33:00

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

ВоляORM value 转для datetime ценить

  • параметр value (str или date или datetime) – Нужно конвертировать ценить
  • возвращаться представлять valueизобъект
  • возвращатьсятип datetime илиNone
Реляционные поля
class odoo.fields.Many2one[исходный код]

Many2oneПолеизценитьэто размердля0(无Записывать)или1(один个Записывать)из Записывать集。

параметр:

  • comodel_name (str) – Название целевой модели,comodel_nameявляется обязательнымпараметр,Если только это не связано или Расширять Поле (не совсем понимаю,оригинальный:name of the target model Mandatory except for related or extended fields)
  • domain – Необязательно для установки ценить кандидата на стороне клиента domain (domain илихарактернить)
  • context (dict) – 处理Должен Полечасдля客户端использоватьизначальство下文
  • ondelete (str) – когда Цитироватьиз Записыватьодеялоудалитьчас,что делать:Необязательныйценитьиметь:'set null', 'restrict', 'cascade'
  • auto_join (bool) – Есть搜索Должен Полечас生成JOIN (по умолчанию: False)
  • delegate (bool) – Воля ЧтонастраиватьдляTrueк标记Сноснотекущий Модельцель доступа Модельиз Поле(верноотвечать_inherits)
  • check_company (bool) – Тег должен быть внутри _check_company()середина校验из Поле。в зависимости от Полесвойство,Добавить домен компании по умолчанию
class odoo.fields.One2many[исходный код]

One2manyПолеизценитьдля comodel_nameсередина所иметь满足条件из Записыватьизрезультат集,И цель Модельсерединаиз inverse_name Это эквивалентно текущей записи.

параметр:

  • comodel_name (str) – Название целевой модели
  • inverse_name (str) – Цель Модельсередина反向Many2oneПолеимя,По данным записи обратного запроса Поле
  • domain – Условия, используемые для установки ценить кандидата клиента (domain илихарактернить),Необязательный
  • context (dict) – 处理Должен Полечасдля客户端использоватьизначальство下文
  • auto_join (bool) – Есть搜索Должен Полечас生成JOIN (по умолчанию: False)
  • limit (int) – Дополнительные ограничения при чтении

comodel_name иinverse_name Параметр является обязательным, если он не связан с или Расширять Поле.

class odoo.fields.Many2many[исходный код]

Many2manyПолеизценитьдляодинрезультат集。

параметр:

  • comodel_name – Название целевой модели, обязательный параметр, если не относится к или Расширять Поле
  • relation (str) – 数据库серединахранилищесвязьизповерхностьимя,Необязательныйпараметр。
  • column1 (str) – relationв таблице Цитировать"Эти"Записыватьиз列имя,Необязательныйпараметр
  • column2 (str) – relationв таблице Цитировать"Вон те"Записыватьиз列имя,Необязательныйпараметр

relation, column1 иcolumn2 параметр Необязательный。 Если не указано, оно генерируется автоматически на основе названия модели, и предоставленное имя не такое. жеизmodel_name иcomodel_name

Уведомление,ORM не поддерживает данную модель,использоватьтакой же样изcomodel,создавать Несколько省немного Понятноrelationпараметриз Поле,потому чтодля Эти Поле Воляиспользовать Взаимнотакой жеизповерхность。ORMвторой блокMany2manyПолеиспользовать Взаимнотакой жеизrelationпараметр,пока не:

  • два Поле Всеиспользовать Взаимнотакой же модель, comodelи显示обозначениеrelationпараметр,в противном случае
  • 至少иметьодин Поле Принадлежат нести_auto = Falseиз Модель

параметр:

  • domain – Условия, используемые для установки ценить кандидата клиента (domain илихарактернить),Необязательный
  • context (dict) – 处理Должен Полечасдля客户端использоватьизначальство下文
  • check_company (bool) – Тег должен быть внутри _check_company()середина校验из Поле。в зависимости от Полесвойство,Добавить условие компании по умолчанию
  • limit (int) – Дополнительные ограничения при чтении

Уведомление:odooНет会существоватьтекущий Модельверноотвечатьв таблицедляOne2many,Many2manyтипизсвойство建立верноотвечатьизповерхность Поле,Но это будетдляMany2oneтипизсвойство建立верноотвечатьповерхность Поле,противMany2manyтипизсвойство,Odoo создаст вспомогательную таблицу,поверхностьимяпо умолчанию Форматдляmodel1_table_name_model2_table_name_rel,В таблице есть два столбца,столбецдлятекущий Модельпервичный ключ таблицыID(model1_table_name_id),столбецдлясвязь Полеассоциация Модельповерхностьизпервичный ключID(model2_table_name_id),такпроходить两поверхность ЗаписыватьID就可к查询所需Записывать Понятно

Поля псевдоотношений
  • class odoo.fields.Reference[исходный код] Поля псевдоотношений(数据库середина没иметьFK)。Должен Полеценитьхранилищедля数据库середина遵循модель"res_model,res_id"изхарактернить。
  • class odoo.fields.Many2oneReference[исходный код] Должен Полеизценитьхранилищедля数据库серединаизодинцелое число。иodoo.fields.ReferenceПоле Взаимно反,должно быть вCharтип Полесерединаобозначение Модель,в,Должен Полеизимядолжно быть втекущийMany2oneReferenceПолесерединаизmodel_fieldсвойствосерединаобозначение параметр:model_field (str) – Сохраняет название модели.
Расчетное поле

Можно использовать compute параметр Расчетное поле(而Нетда直接从数据库серединачитать)этодолжен Волявычислитьценитьточканормирование Поле。еслиэтоиспользовать Что他Полеизценить,ноотвечатьиспользоватьdepends()обозначение Эти Поле

Язык кода:javascript
копировать
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

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

Язык кода:javascript
копировать
@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параметроткрыть в Расчетное поленачальствоиз搜索。ДолженпараметрценитьдляодинвозвращатьсяКритерии поискаизметодимя 。

Язык кода:javascript
копировать
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)]

в праве Модель进行действительный搜索Из前处理domainчасвызов Должен搜索метод。этодолженвозвращатьсяи条件field operator value等效изdomain

Расчетное полепо умолчаниюценить。дляразрешено Расчетное поле进行настраивать,использоватьinverseпараметр。Долженпараметрценитьдля反向вычислитьинастраивать Связанный Полеиз函数изимя:

Язык кода:javascript
копировать
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)

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

Язык кода:javascript
копировать
discount_value = fields.Float(compute='_apply_discount')
total = fields.Float(compute='_apply_discount')

@api.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

предупреждать Хотя можно использовать фазу такой на нескольких Поле. жеизвычислитьметод,但Нет建议верноreverseметодиспользовать Взаимнотакой тот же метод. существоватьreverseизвычислить过程середина,所иметьиспользоватьописалinverseиз Поле Все受到保护,Это значит даже если их ценить нет в кеше,Их также невозможно вычислить. Если вы посетили любой из этих Поле,и его ценить нет в кеше,ORMВоля简одиниздля Эти Полевозвращатьсяпо умолчаниюценитьFalse。этот意味着ЭтиinverseПолеизценить(курокinverseметодизценитькроме)可能Нет会Давать出正确изценить,это может сломатьсяinverseметодиз预期行для

Связанные поля

Расчетное полеизодин种特殊情况даСвязанный(актерское мастерство)Поле,этопоставлятьтекущий Записыватьначальство子Полеизценить。это们дапроходитьнастраиватьrelatedпараметр Приходитьопределениеиз,То же, что и обычное Расчетное поле,Они могут хранить:

Язык кода:javascript
копировать
nickname = fields.Char(related='user_id.partner_id.name', store=True)

relatedПолеизценитьдапроходить遍历один系列связь Полеи прочитайте полученный доступ Модельначальствоиз Поле Приходить Давать出из。要遍历из Полеиз完整序列由relatedсвойствообозначение

Если некоторые свойства Поле не переопределены,но会自动从源Полесерединакопировать Этисвойство:stringhelprequired(толькокогда序列серединаиз所иметь Поле Вседа必需изчас)、groupsdigitssizetranslatecleaning”、“selectioncomodel_namedomainиcontext。所иметь无Семантикасвойство Все从源Полекопировать。

По умолчанию, связанное поле:

  • не хранится
  • Нетодеялокопировать
  • только чтение
  • Вычислено в режиме суперпользователя

картина Расчетное поле туда, добавь store=True кхранилищеrelatedПоле。когда Что依赖одеяло修改час,会自动重новыйвычислитьrelatedПоле。

Советы

если Нет希望существовать任何依赖项更改час重новыйвычислитьrelatedПоле,Затем вы можете указать точные зависимости Поле:

Язык кода:javascript
копировать
nickname = fields.Char(
    related='partner_id.name', store=True,зависит=['partner_id'])
# Псевдоним будет пересчитан только при изменении Partner_id,Он не будет пересчитываться при изменении имени партнера.

предупреждать

Нет可ксуществоватьrelatedПоле依赖项середина Включать Many2many или One2many Поле

related Может использоваться для ссылки на другую модель. One2many илиMany2many Поле,前提дапроходитьтекущий МодельизодинMany2oneсвязь Приходить实现из。 One2many иMany2many Не поддерживается и не может правильно агрегировать результаты:

Язык кода:javascript
копировать
m2o_id = fields.Many2one()
m2m_ids = fields.Many2many()
o2m_ids = fields.One2many()

# Supported
d_ids = fields.Many2many(related="m2o_id.m2m_ids")
e_ids = fields.One2many(related="m2o_id.o2m_ids")

# Won't work: use a custom Many2many computed field instead
f_ids = fields.Many2many(related="m2m_ids.m2m_ids")
g_ids = fields.One2many(related="o2m_ids.o2m_ids")
Автоматически генерируемые поля
  • odoo.fields.id IDПоле Если текущая длина набора записей равна 1, появляется идентификатор уникальной записи в наборе записей. В противном случае выдать ошибку
доступ к полям журнала

если启用_log_access,Автоматически устанавливать и обновлять эти Поле. Когда эти предметы не используются,Отключите его, чтобы предотвратить создание этих обновлений в таблице.

по умолчанию _log_accessодеялонастраиватьдля _autoизценить。

  • odoo.fields.create_date создавать Записыватьчасхранилищесоздаватьчас间,Datetimeтип
  • odoo.fields.create_uid Хранит создателя записи, Many2one to a res.users
  • odoo.fields.write_date хранилище Записывать最后更новыйчас间,Datetimeтип
  • odoo.fields.write_uid Сохраняет человека, который последним обновил запись, Many2one to a res.users.

предупреждать

должно быть правodoo.models.TransientModelМодельвключать_log_access

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

В дополнение к автоматическому Поле,Есть также некоторые имена Поле, которые зарезервированы предопределенной строкой для. Когда нужны связанные строки для,отвечатьсуществовать Модельначальствоопределениеэто们:

  • odoo.fields.name _rec_nameизпо умолчаниюценить,используется при необходимостипредставлятьсекс“имя”изначальство下文середина显示Записывать。odoo.fields.Charтип
  • odoo.fields.active 切换Записыватьиз全局可见секс,еслиactiveнастраиватьдляFalse,но Записыватьсуществовать大много数搜索исписоксередина Нет可见。odoo.fields.Booleanтип
  • odoo.fields.state объектиз声明周期阶段,дляfields.[Selectionиз states Использование атрибута
  • odoo.fields.parent_id _parent_nameизпо умолчаниюценить,Используется для организации записей в древовидной структуре.,и вdomainсередина启用child_ofиparent_ofоператор。Many2oneПоле。
  • odoo.fields.parent_path когда_parent_storeнастраиватьдляTrueчас,用于хранилище反映[_parent_name]树结构изценить,и оптимизировать поискdomainсерединаизchild_ofиparent_ofоператор。должениспользоватьindex=TrueВысказывание может быть правильнымдействовать。odoo.fields.Charтип
  • odoo.fields.company_id 用于OdooМногопрофильная линиядляиз主Полеимя。для:meth:~Odoo.models._check_company用于检查Несколько компанийодин致секс。определение Записывать Есть公司Из间共享(没иметьценить)还датолько Давать定公司из用户доступ。Many2one:тип:res_company

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

и Модельи Записыватьиз交互дапроходить Записывать集осуществлятьиз,Записывать集датакой жеодин Модельиз Записыватьизиметь序собирать。

предупреждать

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

существовать Модельначальствоопределениеизметоддасуществовать Записывать集начальствоосуществлятьиз,методизselfдаодин Записывать集:

Язык кода:javascript
копировать
class AModel(models.Model):
    _name = 'a.model'
    def a_method(self):
        # self can be anything between 0 records and all records in the
        # database
        self.do_operation()

Перебрать набор записей, чтобы создать новый набор записей с одной записью.,этотиверноPythonхарактернить进行迭代产生один个характеризхарактернить非常Взаимно似:

Язык кода:javascript
копировать
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), ...
Доступ к полям

Recordset предоставляет «Активный Record” интерфейс:Модель Поле Можно сделать напрямуюдля Записыватьизсвойство直接читатьиписать。

аннотация

При доступе к нереляционному Поле в наборе записей, состоящем из потенциально нескольких записей.,использоватьmapped(),Функция получила список:

Язык кода:javascript
копировать
total_qty = sum(self.mapped('qty')) # mappedвозвращаться списком вида [2,4,5]

Полеценить также можно получить как словарную статью. Установка цены Поле запускает обновление базы данных:

Язык кода:javascript
копировать
>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"
>>> field = "name"
>>> record[field]
Bob

предупреждать

  • Ошибка при попытке прочитать нереляционное Поле Поле Воляпричина по нескольким записям.
  • доступодинсвязь Поле(Many2one,One2many,Many2many),Всегда устанавливается рекорд,Если Поле не установлено,Затем появляется пустой набор записей.
Кэширование журналов и предварительная выборка

Odoo для Поле поддерживает кеш,так,Не при каждом доступе со стороны Поле будет выполняться запрос к базе данных.

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

Язык кода:javascript
копировать
record.name             # Первый доступ получает ценить из базы данных
record.name             # Второе посещение получает ценить из кеша

для того, чтобы не читать записи по одному Поле за раз,Odoo будет предварительно выбирать записи в соответствии с некоторыми эвристическими правилами.,чтобы получить хорошую производительность. Однажды Поле необходимо прочитать по данной записи,ORM фактически прочитает это Поле в большем наборе записей.,и Волявозвращатьсяизценитьхранится в缓存серединакдля后续использовать。предварительная выборкаиз Записывать集в целомдапроходить迭代获得Записыватьиз Записывать集。также,Все простые хранилища Поле (логическое ценить, целое число, плавающее ценить, символ, текст, дата, дата-время, выбор, много2один) извлекаются и соответствуют столбцам таблицы модели;,и втакой Эффективное получение за один запрос.

Рассмотрим следующий пример,вpartnersдля Включать1000条Записыватьиз Записывать集。если Нет进行предварительная выборка,Цикл Воля запрашивает базу данных 2000 раз. использовать предварительную выборку,Выполните только один запрос

Язык кода:javascript
копировать
for partner in partners:
    print partner.name          # first pass prefetches 'name' and 'lang'
                                # (and other fields) on all 'partners'
    print partner.lang

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

Язык кода:javascript
копировать
countries = set()
for partner in partners:
    country = partner.country_id        # first pass prefetches all partners
    countries.add(country.name)         # first pass prefetches all countries

декоратор метода

Модуль Odoo API определяет модификаторы методов среды Odoo.

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

Украсьте метод так, чтобы он использовался ежедневным пылесосом. cronОперация(Модельir.autovacuum)вызов。этотв целом用于垃圾收集Из类из Нетнуждаться特定cronОперацияиз任务

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

Украсьте средство проверки ограничений

каждыйпараметрдолженда校验использоватьиз Полеимя:

Язык кода:javascript
копировать
@api.constrains('name', 'description')
def _check_description(self):
    for record in self:
        if record.name == record.description:
            raise ValidationError("Fields name and description must be different")

Функция декоратора вызывается при изменении записанного имени.

Если проверка не удалась, она должна выдать ValidationError

предупреждать

@constrains Поддерживаются только простые имена Поле, имена с точками (Поле, связанное с Поле, например partner_id.customer)

@constrains толькокогда修饰методсередина声明из Поле Включатьсуществоватьcreateилиwriteвызовсерединачас才会курок。этот意味着视图середина Нет存существоватьиз Полесуществоватьсоздавать Записывать期间Нет会куроквызов。должен重写create,чтобы гарантировать, что ограничения всегда срабатывают (например,,Тест на отсутствие ценить)

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

стал декоратором,Должен装饰器обозначениеcomputeметодиз Поле依赖связь(дляновый型函数Поле)。параметр支持да由точкаточка隔из Полеимя序列Группа成изхарактернить:

Язык кода:javascript
копировать
pname = fields.Char(compute='_compute_pname')

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

Некоторые могут также передавать функцию как параметр,В этом случае,依赖проходитьвызов существовать В этом случае,проходитьиспользовать Полеиз Модельвызов函数Приходитьпоставлять依赖项

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

Модификатор, определяющий контекстные зависимости для несохраняемых «вычислительных» методов. Каждый параметр является ключом в контекстном словаре:

Язык кода:javascript
копировать
price = fields.Float(compute='_compute_product_price')

@api.depends_context('pricelist')
def _compute_product_price(self):
    for product in self:
        if product.env.context.get('pricelist'):
            pricelist = self.env['product.pricelist'].browse(product.env.context['pricelist'])
        else:
            pricelist = self.env['product.pricelist'].get_default_pricelist()
        product.price = pricelist.get_products_price(product).get(product.id, 0.0)

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

  • company (ценитьили текущий идентификатор компании в контексте),
  • uid (текущий идентификатор пользователя и тег суперпользователя),
  • active_test (env.contextилиfield.contextсерединаизценить).

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

Изменение метода стиля записи,вselfдаодин空Записывать集,но его содержание не имеет значения,Только связанные с моделью,Понятно, что для не создаст объект модели, соответствующий записи базы данных. для работы на уровне модели необходимо добавить этот модификатор,Эквивалент статической функции класса

Язык кода:javascript
копировать
@api.model
def method(self, args):
    ...

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

Измените список словарей для метода параметра и создайте несколько записей. Метод можно вызвать только со словарем и списком словарей:

Язык кода:javascript
копировать
record = model.create(vals)
records = model.create([vals, ...])

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

Получается Декоратор, который изменяет метод onchange данного Поле.

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

Каждый параметр должен быть именем поля:

Язык кода:javascript
копировать
@api.onchange('partner_id')
def _onchange_partner(self):
    self.message = "Dear %s" % (self.partner_id.name or "")
    return {
        'warning': {'title': "Warning", 'message': "What is this?", 'type': 'notification'},
    }

еслитипнастраиватьдляуведомить(notification),Затем в уведомлении появляется Предупредить Воля. в противном случае,Это Воля по умолчанию ценить отображается в диалоговом окне

предупреждать

@onchange только支持简одиниз Полеимя,Нет支持и自动忽немноготочкаточкаимя(связь Полеиз Поле,напримерpartner_id.tz)

Опасность

потому что @onchange возвращаться伪Записыватьиз Записывать集,верноначальство述Записывать集вызов任何одинCRUDметод(create(), read(), write(), unlink())Вседа未определениеиз行для,Потому что их может еще не существовать в базе данных. Напротив,只需картинаначальство面из Примерсередина所示那样настраивать Записыватьиз Полеиливызовupdate()метод

предупреждать

one2many илиmany2manyПоле Нет可能проходитьonchange修改Что自身。этотда客户端предел - Проверять #2693

odoo.api.returns(model, downgrade=None, upgrade=None)[исходный код]

длявозвращатьсяmodel实例изметодвозвращатьсяодин修饰器

  • параметр model – Модельимя,илиозначает, когда前Модельиз'self' downgrade – один用于转换record-styleизvalueдля传统风格输出из函数downgrade(self, value, *args, **kwargs) upgrade – один用于转换传统风格(traditional-style)изvalueдляrecord-styleиз输出из函数upgrade(self, value, *args, **kwargs)

параметр self, *args и**kwargsкrecord-styleСпособперешел метод

Вывод метода модификатора Воля адаптирует стиль API: id, ids илиFalse соответствует традиционному стилю, а набор записей соответствует стилю записи:

Язык кода:javascript
копировать
@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)

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

Эти修饰器да自动унаследованный:重写одеяло修饰из现иметьметодизметод Воляодеяло Взаимнотакой жеиз@return(модель) модификация

среда(Environment)

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

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

  • текущий пользователь (user)
  • курсор (cr)
  • идентификатор суперпользователя(su)
  • или Контекст (context)
Язык кода:javascript
копировать
>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)
>>> self.env.context # появились словарные данные, эквивалентные self._context
{'lang': 'en_US', 'tz': 'Europe/Brussels'}
>>> self._context
{'lang': 'en_US', 'tz': 'Europe/Brussels'}

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

Язык кода:javascript
копировать
>>> 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)

Environment.ref(xml_id, raise_if_not_found=True)[исходный код]

возвращатьсяи Давать定xml_idверноотвечатьиз Записывать。

Environment.lang

станет текущий код языка. появляется тип ул

Environment.user

возвращатьсятекущий пользователь(делатьдляодин实例)。возвращатьсятипres_users

Environment.company

станет текущая компания (сделать для примера)

если не в контексте (allowed_company_ids)серединаобозначение, возвращатьсятекущий Основная компания пользователя (если not specified in the context(allowed_company_ids), fallback on current user companies)

  • причина AccessError – Незаконное илидля авторизации allowed_company_ids Содержание контекстного ключа
  • возвращаться текущий公司(по умолчаниюценить=self.user.company_id)
  • возвращатьсятип res.company

предупреждать

Никакой проверки работоспособности приложения в режиме sudo! В режиме sudo пользователь может получить доступ к любой компании, даже не к той, которую ему разрешено делать.

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

Environment.companies

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

если не в контексте (allowed_company_ids)серединаобозначение, возвращатьсятекущий Основная компания пользователя (если not specified in the context(allowed_company_ids), fallback on current user companies)

  • причина AccessError – Незаконное илидля авторизации allowed_company_ids Содержание контекстного ключа
  • возвращаться текущий公司(по умолчаниюценить=self.user.company_id)
  • возвращатьсятип res.company

предупреждать

Никакой проверки работоспособности приложения в режиме sudo! В режиме sudo пользователь может получить доступ к любой компании, даже не к той, которую ему разрешено делать.

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

Изменить среду

Model.with_context([context][, **overrides]) -> records[исходный код]

Будет новая версия этого набора записей, прикрепленная к контексту Расширять.

Расширятьначальство下文дапоставлятьиз合и Понятноoverridesизcontext,илида合и Понятноoverridesтекущийcontext

Язык кода:javascript
копировать
# 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}

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

Model.with_user(user)[исходный код]

Прикрепите новую версию этого набора записей к данному пользователю как пользователю без прав суперпользователя.,То есть передать запись пользователя и создать среду пользователя.,пока неuserБудьте суперпользователем(как согласовано,Суперпользователь всегда модель суперпользователя)

Model.with_company(company)[исходный код]

появится новая версия этого набора записей с измененным контекстом.,так:

Язык кода:javascript
копировать
result.env.company = company
result.env.companies = self.env.companies | company
  • параметр company (res_company или int) – Главная компания новой среды

предупреждать

когдатекущий пользовательиспользовать未经授权из公司час,Если нет доступа к компании в sudoedсреда,но可能会курокAccessError

Model.with_env(env)[исходный код]

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

  • параметр env (Environment) –

предупреждать

Новая среда Воля не будет использовать кэш данных текущей среды.,поэтому稍后из数据доступ可能会существовать从数据库重новыйполучать数据час产生额外из延迟。возвращатьсяиз Записывать集具иметьиselfВзаимнотакой же предварительная выборка объекта.

Model.sudo([flag=True])[исходный код]

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

предупреждать

использоватьsudo可能会导致数据доступ跨越Записывать规ноиз边界,Может возникнуть путаница относительно того, какие записи следует поместить в карантин (например,,Несколько компанийсредасередина Приходить自Неттакой те же записи компании).

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

аннотация

Потому что для необходимо переоценить правила ведения журнала и контроль доступа.,Таким образом, новый набор записей Воля не будет использовать кэш данных текущей среды.,поэтомук后из数据доступ可能会существовать从数据库重новыйполучатьчас产生额外из延迟。возвращатьсяиз Записывать集具иметьиselfВзаимнотакой же предварительная выборка объекта.

выполнение SQL

среданачальствоизcrсвойстводатекущий数据库事务изкурсор,Разрешить прямой доступосуществлятьSQL,Будь тодля难киспользоватьORMповерхность达из查询(Напримерсложныйjoin),или по соображениям производительности

Язык кода:javascript
копировать
self.env.cr.execute("some_sql", params)

потому что Модельиспользовать Взаимнотакой жеизкурсор,ииEnvironmentСохраняйте различные тайники,поэтомукогдасуществовать原始SQLсередина更改数据库час,Эти кеши должны быть признаны недействительными.,в противном случае Модельиз进один步использовать可能会变得Нет连贯。существоватьSQLсерединаиспользоватьCREATEUPDATEилиDELETE,但НетиспользоватьSELECT(только чтения при выборке базы данных) кэш необходимо очистить.

аннотация

Можно использовать invalidate_cache()осуществлять缓存из清理

  • Model.invalidate_cache(fnames=None, ids=None)[исходный код] 修改某些Записывать后,使Записывать缓存无效。еслиfnamesиidsВседляNone,но清除整个缓存。 параметр: fnames–Модифицированный Полеизсписок,Noneповерхность示所иметь Поле ids–修改из ЗаписыватьIDизсписок,Noneповерхность示所иметь Записывать

предупреждать

Выполнение необработанного SQL обходит ORM, тем самым обходя правила безопасности Odoo. Обязательно очищайте свои запросы при использовании пользовательского ввода, а если вам действительно не нужно использовать запросы SQL, используйте утилиту ORM.

Распространенные методы ORMОбщие методы ORM

Создать/обновить(Создать/обновить)

Model.create(vals_list) → records[исходный код]

для Модельсоздаватьновый рекорд

использоватьсловарьсписокvals_listсерединаизценитьисходный化новый рекорд,если необходимо,использоватьdefault_get()серединаизценить

  • параметр vals_list (list) --Модель Полеизценить,делатьдлясловарьсписок:[{'field_name':field_value,…},…]дляобратная совместимость,vals_listможет бытьодинсловарь。этоодеяло视дляодин个список[vals],ивозвращатьсяодин条Записывать。иметь关详细信息пожалуйста参见write()
  • возвращаться записи созданы
  • причина AccessError
    • Если у пользователя нет разрешений на создание запрошенного объекта
    • Если пользователь пытается обойти правила доступа, созданные для запрошенного объекта

    ValidationError – Если пользователь пытается ввести неверную цену, которая находится за пределами выбора UserError–если Волясуществоватьобъект层次结构серединасоздаватьцикл,Результат действия (например, воляобъект устанавливает свой собственный родительский объект)

Model.copy(default=None)[исходный код]

использоватьпо умолчаниюценить更новый拷贝из Записыватьself

  • параметр default (dict) – Словарь Полеценить, используемый для перезаписи исходной цены, записанной копировать, в форме: {'field_name': overridden_value, ...}
  • возвращаться новый рекорд

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

возвращатьсяfields_listсередина Полеизпо умолчаниюценить。по умолчаниюценить由начальство下文、用户по умолчаниюценитьи Модельрешай сам

  • параметр fields_list (list) – Нужно получить имя поляка по умолчанию ценить
  • возвращаться Словарь имен Воля Поле сопоставлен с соответствующей ценой по умолчанию (если она есть).
  • возвращатьсятип dict

аннотация

Незапрошенная цена по умолчанию не учитывается.,Нетнуждатьсядляимя Нетсуществоватьfields_listсерединаиз Полевозвращатьсяценить。

Model.name_create(name) → record[исходный код]

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

новый рекорд Воляиспользовать Применимый于此Модельиз任何по умолчаниюценитьисходный化,илипроходитьначальство下文поставлять。create()изв целом行для Применимый

  • параметр name – Отображаемое имя создаваемой записи.
  • возвращатьсятип кортеж
  • возвращаться записи созданыизname_get() попарноценить

Model.write(vals)[исходный код]

использоватьпоставлятьизценить更новыйтекущий Записывать集серединаиз所иметь Записывать

параметр:

vals (dict) –нуждаться更новыйиз Поле及верноотвечатьизценить,например:{'foo': 1, 'bar': "Qux"} ,Волянастраивать foo ценитьдля 1 , bar для"Qux",Если бы это было законно,в противном случае Волякурок错误。нуждаться特别Уведомлениеизда,Тем больше Поле нужно обновлять,Чем медленнее скорость обновления (автор обнаружил на практике,Но я не проверял, связано ли это с типом и Поле,Особенно отношения Поле,связь Полеиз更новый可能会вызовверноотвечать Модельизwriteметод,Если этот метод переопределен,Это также может привести к увеличению затрат времени,в общем,соблюдать принцип,Обновляйте только те элементы, которые необходимо обновить)

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

    ValidationError – Если пользователь пытается ввести неверную цену, которая находится за пределами выбора UserError–если Волясуществоватьобъект层次结构серединасоздаватьцикл,если в результате операции в иерархии объектов будет создан цикл (например, установка объекта в качестве собственного родителя)

дляцифровой Поле(odoo.fields.Integer,odoo.fields.Float) ,ценить должно соответствовать типу

для odoo.fields.Boolean, ценитьдолжендляboolтип

дляodoo.fields.Selection, ценитьдолженсоответствоватьвыбиратьценить(в целомдляstr,иметьчасдляint)

дляodoo.fields.Many2one,ценитьMustдля Идентификатор записи в базе данных

Другие не-отношения,использоватьхарактернитьценить

Опасность

По историческим причинам и соображениям совместимости,odoo.fields.Dateиodoo.fields.DatetimeПолеиспользоватьхарактернитьделатьдляценить(писатьичитать),而Нетдаdateилиdatetime。ЭтидатахарактернитьтолькодляUTCФормат,ив соответствии сodoo.tools.misc.DEFAULT_SERVER_DATE_FORMATиodoo.tools.miisc.DEFAULT_SERVER _DATETIME_FORMAT进行Формат化

odoo.fields.One2manyиodoo.fields.Many2manyиспользовать特殊из“Заказ”Формат Приходитьдействоватьхранится в Полесередина/и Полеассоциацияиз Записывать集。

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

  • (0, 0, values) 从поставлятьизvaluesсловарьсоздаватьновый рекорд,形нравиться (0, 0, {'author': user_root.id, 'body': 'one'})
  • (1, id, values) использоватьvaluesценить обновление idценитьдля в указанном словареidСуществующие записи для ценить. Нет могу быть там create()серединаиспользовать。
  • (2, id, 0) 从Записывать集серединаудалитьidдляобозначениеidиз Записывать,Затем удалите его (из базы данных) Не могу быть там create()серединаиспользовать。
  • (3, id, 0) 从Записывать集серединаудалитьidдляобозначениеidиз Записывать,但Нетудалитьэто。Не могу быть там create()серединаиспользовать。
  • (4, id, 0) 添加один条idдляобозначениеidиз已存существовать Записывать到Записывать集
  • (5, 0, 0) Удалить все записи из набора результатов, Эквивалентно显示изверно每条Записыватьиспользовать Заказ3。 Не могу быть там create()серединаиспользовать。
  • (6, 0, ids) в соответствии сidsсписок,替换所иметь已存существовать Записывать, Эквивалентноиспользовать Заказ(5, 0, 0),Затем, чтобыidsсерединаизкаждыйidиспользовать Заказ(4, id, 0)。Практические выводы,Против One2manyПоле,еслиidsверноотвечать ЗаписыватьизMany2oneПоле没хранилищетекущий Модельпервичный ключIDценитьчас,Не могущийиспользовать Должен Заказ。

действительныйиспользоватьчас,Эти Заказ可к Группа合использовать,следующее,ДаватьfieldNameнастраиватьценитьчас,会先обозначение Заказ5,существоватьосуществлять Заказ 0

Язык кода:javascript
копировать
Model.write({'fieldName': [(5, 0, 0), (0, 0, dict_value)]})

Model.flush(fnames=None, records=None)[исходный код]

处理所иметьобращаться定извычислить(существовать所иметь Модельначальство),Обработайте все ожидающие вычисления (на всех моделях) и сбросьте все ожидающие обновления в базу данных.

  • параметр fnames – Список имен поляков, которые необходимо обновить. если дано, то Воля обрабатывает предел диапазона для данного Поле текущей модели. records – если дано (ассоциациятакой же fnames), Ограничить область обработки заданными записями.
Поиск/Чтение

Model.browse([ids]) → records[исходный код]

существоватьтекущийсредасередина查询idsпараметробозначениеиз Записыватьивозвращаться Записыватьрезультат集,Если для предложения параметр,илипараметрдля[],Затем появляется пустой набор результатов

Язык кода:javascript
копировать
self.browse([7, 18, 12])
res.partner(7, 18, 12)
  • параметр ids (int или list(int) или None) – id(s)
  • возвращаться recordset

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

на основеargs поиск домена搜索Записывать

  • параметр argsпоиск домена。использовать[]представлятьсоответствовать所иметь Записывать。 offset (int) – Результаты, которые следует игнорировать записей (по умолчанию: 0) limit (int) – максимумвозвращаться Количество записей (по умолчаниювозвращаться所иметь) order (str) – Сортировать строку count (bool) – еслидляTrue,тольковычислитьивозвращатьсясоответствоватьиз Количество записей (по умолчанию: False)
  • возвращаться большинствоlimitСтатьи совпадают Критерии запись определения
  • причина AccessError – Если пользователь пытается обойти правила доступа для чтения запрошенного объекта

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

возвращатьсятекущий Модельсерединасоответствоватьпоставлятьизпоиск доменаargsиз Количество записей.

Model.name_search(name='', args=None, operator='ilike', limit=100) → records[исходный код]

搜索Сравнивать显示имяи Давать定nameсоответствовать(соответствовать Способдля Давать定operator),исоответствоватьпоиск доменаargsиз Записывать

Например,этот用于на основесвязь Полеиз部точкаценитьпоставлять建议。иметьчасодеяло视дляname_get()из反函数,Но нет никакой гарантии, что это так.

此метод等效于использоватьна основеdisplay_nameизпоиск доменавызовsearch(),Затемверно搜索результатосуществлять“name_get()”关于搜索результат

  • параметр name (str) – Должно совпадать с именем args (list) – Дополнительный поиск домена, Далее укажите ограничения operator (str) – 用于соответствоватьnameиз域действовать,например 'like' или '=' limit (int) – Необязательныйпараметр,возвращатьсямаксимум Количество записей
  • возвращатьсятип list
  • возвращаться 所иметьсоответствовать Записыватьизверноценить(id, text_repr)список

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

читатьselfсередина Записыватьизобозначение Поле, низкий уровень/RPCметод。Python代码середина,предпочтительныйbrowse().

  • параметр fields – нуждатьсявозвращатьсяиз Полеимя(по умолчаниювозвращаться所иметь Поле)
  • возвращаться Список словарей с названием такой жеитценить маппинг, один словарь на запись
  • причина AccessError – Если у пользователя нет разрешения на чтение данной записи

Model.read_group(domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True)[исходный код]

получатьсписок视图серединав соответствии с Давать定groupbyПолеточка Группаиз Записыватьсписок。

  • параметр domain (list) – поиск домена。использовать[]поверхность示соответствовать所иметь fields (list) – объектначальствообозначениеизсписок视图середина存существоватьиз Полесписок。каждый元素Или“field”(Полеимя,использоватьпо умолчаниюполимеризация),Или“field:agg”(использоватьполимеризация函数“agg”полимеризация Поле),Либо это“name:agg(field)”(использовать“agg'полимеризация Полеи Воля Чтокогда做“name”возвращаться)。可能изполимеризация函数дляPostgreSQLпоставлятьиз函数(https://www.postgresql.org/docs/current/static/functions-aggregate.html),и «count_dict»,具иметь预期含义。 groupby (list) – Записыватьточка Группа依据източка Группа依据描述список。groupby描述Или Поле(Затем Воляв соответствии с Должен Полеточка Группа),Либо строка «поле:groupby_function». в настоящий момент,唯один支持из函数даdayweekmonthquarterилиyear,это们只Применимый于date/datetimeПоле offset (int) – Количество, которое нужно пропустить записи, необязательный параметр. limit (int) – нуждатьсявозвращатьсяизмаксимум Количество записи, необязательный параметр orderby (str) – Сортировать строку(текущийтолько支持Many2oneПоле)。Необязательныйпараметр。 lazy (bool) – еслидляTrue,норезультат只в соответствии с第одинgroupbyточка Группа,Что余groupbyвставить__context键середина。еслидляFalse,Тогда вся группировка выполняется за один вызов.
  • возвращаться словарьсписок(每条Записыватьодинсловарь)。Включать:в соответствии сgroupbyпараметрсерединаобозначение Полеточка Группа后из Полеизценить __domain: обозначение Критерии Список кортежей по заявкам __context: 拥иметьпохожийgroupbyпараметризсловарь
  • возвращатьсятип [{‘field_name_1’: value, …]
  • причина AccessError – Если у пользователя нет разрешения на чтение запрошенного объекта, Если пользователь пытается обойти правило доступа, прочтите запрошенный объект.

Model.copy_data()

拷贝текущий Модель Записыватьиз数据,появился словарь,Ключ словарядля модели Название поля,keyценитьдляверноотвечатьиз Полеценить。Уведомление:возвращатьсясловарьkeyНет ВключатьOdoo系统自动生成из Модельповерхность Поле:create_uid,create_date,write_date,write_uid,id

Поля/представления
  • Model.fields_get([fields][, attributes])[исходный код] станет определение каждого поляка придет ценить - словарь, содержащий словари (индексированные по имени Поле). В том числе наследство Поле. Строка ВоляConvert, атрибуты helpиselection (если есть)
    • параметр fields – Поле списка, если未поставлятьилидля[]ноповерхность示所иметь attributes – Каждому Поле требуется список описаний атрибутов для появления. если未поставлятьилидля[]ноповерхность示所иметь
  • Model.fields_view_get([view_id | view_type='form'])[исходный код] Получите подробный состав запрошенного представления, например Поле, модель, архитектуру представления.
    • параметр view_id (int) – Посмотреть IDили Нет view_type (str) – возвращаться视图изтип,еслиview_idдляNoneиз话(‘form’, ‘tree’, …) toolbar (bool) – настраиватьдляTrueк Включатьначальство下文действовать submenu – Устарело
    • возвращаться Состав запрошенного представления (включая унаследованные представления и Расширять)
    • возвращатьсятип dict
    • причина AttributeError – Если унаследованное представление имеет неизвестную позицию, кроме «до», «после», «внутри», «заменить». затем, если в родительском представлении обнаружена отметка, отличная от «позиции» Invalid ArchitectureError – Если в фреймворке определена форма, tree, calendar, search взгляды, отличные от
Поиск доменов

домен — это список критериев,каждыйстандартный Вседа(field_name,operator,value)из三кортеж(один“список”или“кортеж”),в:

  • field_name (str) Поле имени текущего модуля илипроходитьMany2one,использоватьточка符Числоизсвязь遍历,Например 'street' или'partner_id.country'
  • operator (str) 用于Сравниватьfield_nameиvalueизоператор。иметь效оператордля:
    • = равный
    • != Нетравный
    • > больше, чем
    • >= больше, чемравный
    • < меньше, чем
    • <= меньше, чемравный
    • =? 未настраиватьилиравный(еслиvalueдляNoneилиFalseновозвращатьсяTrue,в противном случаеи=один样)
    • =like Воляfield_nameтакой жеvalueмодельсоответствовать。модельсерединаиз下划线_соответствовать任何один个характер;стоточка Число%соответствовать任何ноль个или Несколькохарактеризхарактернить
    • like Воляfield_nameтакой же%value%модельсоответствовать。похожий=like,但дасоответствовать前использовать%Упаковкаvalue
    • not like не соответствует %value% модель
    • ilike С учетом регистраlike
    • not ilike С учетом регистра not like
    • =ilike С учетом регистра =like
    • in равныйvalueсерединаиз任意项,valueотвечать Должендля项список
    • not in Нетравныйvalueсерединаиз任意项
    • child_of даvalueЗаписыватьизchild(Потомки)(valueможет бытьодин项илиодин项список)。учитывать Модельиз Семантика(то есть следуя_parent_nameимяизсвязь Поле)。
    • parent_of даvalueЗаписыватьизparent(предок)(valueможет бытьодин项илиодин项список)。учитывать Модельиз Семантика(то есть следуя_parent_nameимяизсвязь Поле)
  • value Тип переменной, должен быть такой сравнение женаминга Поле (через operator)

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

  • '&' логика AND, По умолчанию используется действие, которое сочетается с условиями Воли. Арити 2 (Используйте следующие 2 стандарта или комбинации)
  • '|' логика OR arity 2
  • '!' логика *NOT * arity 1

пример:

搜索Приходить自比利часили德国имядляABC,Партнеры, чей язык не английский:

Язык кода:javascript
копировать
[('name','=','ABC'),
 ('language.code','!=','en_US'),
 '|',('country_id.code','=','be'),
     ('country_id.code','=','de')]

Домен интерпретируется для:

Язык кода:javascript
копировать
    (name is 'ABC')
AND (language is NOT english)
AND (country is Belgium OR Germany)
unlink
  • Model.unlink()[исходный код] Удалить записи из текущего набора записей причина AccessError – Если у пользователя нет разрешения на отсоединение запрошенного объекта Если пользователь пытается обойти правила доступа, выполните отсоединение объекта запроса. UserError – Если запись является атрибутом по умолчанию для других записей
Записать (установить) информацию

Model.ids

возвращатьсяиselfверноотвечатьизнастоящий实ЗаписыватьID

odoo.models.env

возвращаться Давать定Записывать集изсреда。типEnvironment

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

появляется сам по себе в подмножестве записей и Воля удаляет записи, отмеченные для записей в кеше.

Язык кода:javascript
копировать
if record.exists():
    ...

в соответствии с约定,Воляновый рекордделатьдля现иметь Записыватьвозвращаться

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

Убедитесь, что текущий набор записей содержит только одну запись.

причинаodoo.exceptions.ValueErrorlen(self) != 1

Model.name_get() → [id, name, ...][исходный код]

возвращатьсяselfсередина Записыватьизтекстповерхность示形式。По умолчанию,дляdisplay_nameПолеизценить。

  • возвращаться каждой записи (id, text_repr) Список пар ценить
  • возвращатьсятип list(tuple)

Model.get_metadata()[исходный код]

появятся метаданные о данной записи

  • возвращаться Список словарей владения для каждой запрошенной записи list of ownership dictionaries for each requested record
  • возвращатьсятип Список словарей со следующими ключевыми словами:
    • id: объектID
    • create_uid: пользователь, создавший запись
    • create_date: дата создания записи
    • write_uid: пользователь, который последним изменил запись.
    • write_date: дата последнего изменения записи.
    • xmlid: XML, используемый для ссылки на эту запись ID(еслииметь),Форматдляmodule.name
    • noupdate: Логическое значение, указывающее, была ли обновлена ​​запись.
действовать

Набор записей является неизменяемым,Но Можно использовать различные коллекции, комбинируя такие же коллекции моделей.,Так появился новый рекорд

  • record in set возвращаться record (Должен быть набор записей, содержащий только один элемент) Есть setсередина。 record not in set Как раз наоборот
  • set1 <= set2 andset1 < set2 возвращатьсяset1лидаset2из子集
  • set1 >= set2 and set1 > set2 возвращатьсяset1лидаset2из超集
  • set1 | set2 станет объединением двух наборов рекордов. Набор записей, содержащий все записи, которые присутствуют в обоих исходных наборах записей.
  • set1 & set2 Получится пересечение двух наборов рекордов. В одном содержится только такой То же самое является набором записей, когда в двух исходных наборах записей есть записи.
  • set1 - set2 возвращатьсяодин Включатьтолько Появиться вset1серединаиз Записыватьиз Записывать集

Набор записей является итерируемым,поэтомув целомизPythonИнструменты, доступные для конвертации(map(),sorted(),ifilter(),…),Затем Эти函数возвращатьсяlistилиiterator,удалитьвернорезультатвызовметодилииспользоватьсобиратьдействоватьиз能力。

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

Filter

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

  • параметр func (можно назвать объектом или str) – Функция или последовательность имен Поле, разделенных точками.
  • возвращаться Набор записей, удовлетворяющий func, может быть пустым.
Язык кода:javascript
копировать
# 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")

Model.filtered_domain(domain)[исходный код]

Map

Model.mapped(func)[исходный код]

верноselfсерединаиз所иметь Записыватьприложениеfunc,и Волярезультатделатьдлясписокили Записывать集возвращаться(еслиfuncвозвращаться Записывать集)。последнийвозвращатьсяиз Записывать集из顺序да任意из。

  • параметр func (можно назвать объектом или str) – Функция или последовательность имен Поле, разделенных точками.
  • возвращаться еслиfuncдляFalseновозвращатьсяself делать用于所иметьselfсередина Записыватьизfuncизвозвращатьсярезультат
  • возвращатьсятип list или recordset
Язык кода:javascript
копировать
# returns a list of summing two fields for each record in the set
records.mapped(lambda r: r.field1 + r.field2)

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

Язык кода:javascript
копировать
# returns a list of names
records.mapped('name')

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

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

аннотация

Начиная с V13, Поддержка Дуодуо Гуаньси к полям, работает как сопоставленный вызов:

Язык кода:javascript
копировать
records.partner_id  # == records.mapped('partner_id')
records.partner_id.bank_ids  # == records.mapped('partner_id.bank_ids')
records.partner_id.mapped('name')  # == records.mapped('partner_id.name')
Sort

Model.sorted(key=None, reverse=False)[исходный код]

возвращатьсяв соответствии сkey排序из Записывать集 self

  • параметр key (можно назвать объектомили ул. или None) – одинпараметриз函数,для Один ключ сравнения на запись,или Полеимя,илиNone,еслидляNone,Записыватьв соответствии с照по умолчанию Модельиз顺序排序 reverse (bool) – еслидляTrue, получится результат сортировки в обратном порядке
Язык кода:javascript
копировать
# sort records by name
records.sorted(key=lambda r: r.name)

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

Odoo предлагает три различных типа жеиз机制,к模块化Способ Расширять Модель:

  • Создайте новую модель на основе существующей модели, добавив в копию новую информацию, но сохранив исходный модуль.
  • Расширять Что他模块серединаопределениеиз Модель,Заменить предыдущую версию
  • Воля Модельизодин些Поле委派Даватьэто Включатьиз Записывать
Классическое наследование

когдатакой жечасиспользовать_inheritи _name свойствочас,Odooиспользовать现иметь Модель(проходить_inheritпоставлять)делатьдляbaseсоздаватьновый Модель。новый Модель从Чтоbaseсерединаполучать所иметь Поле、Метод и метаинформация (по умолчанию ценить и т.д.).

Язык кода:javascript
копировать
class Inheritance0(models.Model):
    _name = 'inheritance.0'
    _description = 'Inheritance Zero'

    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'
    _description = 'Inheritance One'

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

Используйте их:

Язык кода:javascript
копировать
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继承один样。

проиллюстрировать:

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

Модель继承会继承父类серединаиз所иметьсвойство,Поле, атрибуты и методы будут скопированы.

可ктакой жечас继承Несколько Модель,например:

Язык кода:javascript
копировать
_inherit = ['res.partner', 'md.status.mixin']
Расширять

когдаиспользовать_inherit但省немного_nameчас,Новая модель Воля заменяет существующую модель.,实质начальство就дасуществоватьоригинальный Модельначальство Расширять。этотдля Воляновый Полеилиметод添加到现иметь Модель(существовать Что他模块серединасоздавать)или Настроитьили重новый Конфигурацияэто们(Например更改Чтопо умолчанию排序顺序)非常иметь用:

Язык кода:javascript
копировать
class Extension0(models.Model):
    _name = 'extension.0'
    _description = 'Extension zero'

    name = fields.Char(default="A")
    
    def func():
        print('test a')

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

    description = fields.Char(default="Extended")
    
    def func(): # Функция переопределения
        print('test b')
Язык кода:javascript
копировать
record = env['extension.0'].create({})
record.read()[0]

возвращаться:

Язык кода:javascript
копировать
{'name': "A", 'description': "Extended"}

аннотация

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

Язык кода:javascript
копировать
env['extension.0'].func({})

возвращаться:

Язык кода:javascript
копировать
test b

Уведомление:

Если такой же наследует абстрактный модуль и неабстрактный модуль,и把_nameКонфигурациядлянеабстрактный модуль,Поле абстрактного модуля также будет добавлено в таблицу, соответствующую неабстрактному модулю.

Делегация

Третий механизм наследования обеспечивает большую гибкость (может быть изменен во время выполнения).,Но менее мощный:использовать_inheritsМодель,Волятекущий Модельсередина未找到из任何Полеиз查找委托Давать“children”Модель。委托проходитьReferenceосуществлятьсуществовать父Модельначальство Автоматически устанавливаетсяиз Поле。

主要区别существовать于意义。использовать委托час,Модельhas one而Нетдаis one,тем самым Волясвязь Конвертировать для Группа合而Нетда继承:

Язык кода:javascript
копировать
class Screen(models.Model):
    _name = 'delegation.screen'
    _description = 'Screen'

    size = fields.Float(string='Screen Size in inches')

class Keyboard(models.Model):
    _name = 'delegation.keyboard'
    _description = 'Keyboard'

    layout = fields.Char(string='Layout')

class Laptop(models.Model):
    _name = 'delegation.laptop'
    _description = 'Laptop'

    _inherits = {
        'delegation.screen': 'screen_id',
        'delegation.keyboard': 'keyboard_id',
    }

    name = fields.Char(string='Name')
    maker = fields.Char(string='Maker')

    # a Laptop has a screen
    screen_id = fields.Many2one('delegation.screen', required=True, ondelete="cascade")
    # a Laptop has a keyboard
    keyboard_id = fields.Many2one('delegation.keyboard', required=True, ondelete="cascade")
Язык кода:javascript
копировать
record = env['delegation.laptop'].create({
    'screen_id': env['delegation.screen'].create({'size': 13.0}).id,
    'keyboard_id': env['delegation.keyboard'].create({'layout': 'QWERTY'}).id,
})
record.size
record.layout

Воля дает результаты:

Язык кода:javascript
копировать
13.0
'QWERTY'

Вы можете изменить комиссию напрямую:

Язык кода:javascript
копировать
record.write({'size': 14.0})

предупреждать

использовать委托继承час,Метод не наследуется,Только Поле

предупреждать

  • _inherits илимногоилименее осознанный,если可киз话避免用это(_inherits is more or less implemented, avoid it if you can)
  • 链式из_inherits基本начальство没иметь实现,我们Нетверно最终行длядавать какие-либо гарантии。(chained _inherits is essentially not implemented, we cannot guarantee anything on the final behavior)
Определение приращения поля

Полеопределениедля Модель类из类свойство。если Расширять Понятно Модель,还可кпроходитьсуществовать子类начальство重новыйопределение具иметь Взаимнотакой жеимяитипиз Поле Приходить Расширять Полеопределение。существовать В этом случае,Атрибуты Поле взяты из родительского класса,и переопределяется свойствами, заданными в подклассах.

Например,下面извторой类толькосуществоватьstateПоленачальство添加工具提示:

Язык кода:javascript
копировать
class First(models.Model):
    _name = 'foo'
    state = fields.Selection([...], required=True)

class Second(models.Model):
    _inherit = 'foo'
    state = fields.Selection(help="Blah blah blah")

Начиная

Определение модели

odoo14\custom\estate\models\estate_property_tag.py

Язык кода:javascript
копировать
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models, fields

class EstatePropertyTag(models.Model):
    _name = 'estate.property.tag'
    _description = 'estate property tag'
    _order = 'name'

    name = fields.Char(string='tag', required=True)
    color = fields.Integer(string='Color')

odoo14\custom\estate\models\estate_property_offer.py

Язык кода:javascript
копировать
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models, fields

class EstatePropertyOffer(models.Model):
    _name = 'estate.property.offer'
    _description = 'estate property offer'

    property_id = fields.Many2one('estate.property', required=True)
    price = fields.Integer()

odoo14\custom\estate\models\estate_property_type.py

Язык кода:javascript
копировать
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models, fields

class EstatePropertyType(models.Model):
    _name = 'estate.property.type'
    _description = 'estate property type'

    name = fields.Char(string='name', required=True)

odoo14\custom\estate\models\estate_property.py

Язык кода:javascript
копировать
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from odoo import models, fields

class EstateProperty(models.Model):
    _name = 'estate.property'
    _description = 'estate property table'
    _order = 'id desc'

    name = fields.Char(required=True)
    property_type_id = fields.Many2one("estate.property.type", string="PropertyType")
    tag_ids = fields.Many2many("estate.property.tag")
    offer_ids = fields.One2many("estate.property.offer", "property_id", string="PropertyOffer")
ОРМдействовать на практике
Язык кода:javascript
копировать
>>> self.env['estate.property.type']
estate.property.type()

# Создать одну запись
>>> self.env['estate.property.type'].create({'name':'house'})
estate.property.type(1,)

# Запрос записей по идентификатору
>>> self.env['estate.property.type'].browse([1])
estate.property.type(1,)
# Если список идентификаторов не указан и параметр не указан, появляется пустой набор записей.
>>> self.env['estate.property.type'].browse()
estate.property.type()
>>> self.env['estate.property.type'].browse([])
estate.property.type()

# копировать Записывать
>>> self.env['estate.property.type'].browse([1]).copy({'name':'garden'})
estate.property.type(2,)

# Для набора записей, который получает только одну запись, вы можете передать records.fieldName Способ цитирования соответствует Поле (читай Полеценить или присваивает ценить Поле)
>>> self.env['estate.property.type'].browse([2]).name 
'garden'

# 更новый рекорд
>>> self.env['estate.property.type'].browse([1]).name
'house'
>>> self.env['estate.property.type'].browse([1]).write({'name':'garden'})
True
>>> self.env['estate.property.type'].browse([1]).name
'garden'
# Для набора записей, который получает только одну запись, вы можете передать records.fieldName Способ цитирования соответствует Поле (читай Полеценить или присваивает ценить Поле)
>>> self.env['estate.property.type'].browse([1]).name = 'house'
>>> self.env['estate.property.type'].browse([1]).name
'house'
# Вы не можете изменить его напрямую, попытавшись указать идентификатор в функции записи следующим образом. рекорд # Никакие записи не будут изменены и никакие записи не будут добавлены.
>>> self.env['estate.property.type'].write({'id':1, 'name':'apartment'}) 
True
>>> self.env['estate.property.type'].browse([1]).name
'house'


# по поиску набор записей запроса API
>>> self.env['estate.property.type'].search([])
estate.property.type(1, 2)

# Создание записей в пакетном режиме
# Создать тестовые данные
>>> self.env['estate.property.tag'].create([{'name': 'tag1', 'color': 1}, {'name': 'tag1', 'color': 2}, {'name': 'tag1', 'color': 3}])
estate.property.tag(1, 2, 3)

# Уведомление: Many2one введите ценить Поле, должен быть установлен идентификатор первичного ключа соответствующей записи для.
>>> self.env['estate.property'].create({'name': 'house in beijing', 'property_type_id': 1, 'tag_ids':[(0,0, {'name': 'tag1', 'color': 3})]})
estate.property(1,)
>>> self.env['estate.property'].search([]) 
estate.property(1,)

# Отношения запроса Полеценить
>>> self.env['estate.property'].browse([1]).property_type_id # Many2one
estate.property.type(1,)
>>> self.env['estate.property'].browse([1]).tag_ids  # Many2many
estate.property.tag(4,)

# Обновить отношения Many2many Полеценить
>>> self.env['estate.property'].browse([1]).tag_ids.write({'name': 'tag4', 'color': 4})
True
>>> self.env['estate.property'].browse([1]).tag_ids.color
4

>>> self.env['estate.property.tag'].search([])
estate.property.tag(1, 2, 3, 4)

# Отношения запроса Полеценить
>>> self.env['estate.property'].browse([1]).offer_ids # One2many
estate.property.offer()

## Обновить отношения One2many Полеценить
# дляRelationship Поле Создать связанную запись
# (0, 0, values)
# Создать новый из предоставленного словаря `values`. рекорд。
>>> self.env['estate.property'].browse([1]).offer_ids = [(0, 0, {'property_id':1})]
>>> self.env['estate.property'].browse([1]).offer_ids
estate.property.offer(1,)
>>> self.env['estate.property'].browse([1]).offer_ids.property_id
estate.property(1,)

# Обновить атрибут отношения Поле по записи объекта ценить
# (1, id, values)
# использовать values ценить обновление idценитьдля в указанном словаре id Существующие записи для ценить. Нет могу быть там Используется в create().
>>> self.env['estate.property'].browse([1]).offer_ids = [(1, 1, {'price': 30000})]
>>> self.env['estate.property'].browse([1]).offer_ids.price
30000

# Удалить связанные записи Поле отношений
# (3, id, 0)
# Удалить запись с идентификатором дid из набора записей, но не удалить ее из базы данных, подразумевается, что для только разъединяет. Нет могу быть там Используется в create().
>>> self.env['estate.property'].browse([1]).offer_ids = [(3,1,0)]
>>> self.env['estate.property'].browse([1]).offer_ids
estate.property.offer()

# Воля已存существовать Записыватьтакой же Ассоциация «Поле отношений»
# (4, id, 0)
# Добавьте существующую запись с idдляid в набор записей.
>>> self.env['estate.property.offer'].browse([1])
estate.property.offer(1,)
>>> self.env['estate.property'].browse([1]).offer_ids = [(4,1,0)]
>>> self.env['estate.property'].browse([1]).offer_ids
estate.property.offer(1,)

# для Поле отношений Создание нескольких связанных записей одновременно
>>> self.env['estate.property'].browse([1]).offer_ids = [(0, 0, {'property_id':1, 'price': 100000}),(0, 0, {'property_id':1, 'price': 200000}), (0, 0, {'property_id':1, 'price': 200000}), (0, 0, {'property_id':1, 'price': 300000})]
>>> self.env['estate.property'].browse([1]).offer_ids
estate.property.offer(1, 2, 3, 4, 5)

# Заменить записи, связанные с отношением Поле
# (6, 0, ids) 
# Заменить все существующие записи на основе списка идентификаторов, Эквивалентно использованию команды (5, 0, 0), затем используйте команду (4, id, 0)。
>>> self.env['estate.property'].browse([1]).offer_ids = [(3,1,0),(3,2,0)]
>>> self.env['estate.property'].browse([1]).offer_ids
estate.property.offer(3, 4, 5)
>>> self.env['estate.property'].browse([1]).offer_ids = [(6, 0, [1,2])] # Сообщить об ошибке, Потому что дляID 1,2 Соответствующая запись, чья Many2oneПолеценитьдляnull

# отношение дляMany2many Поле создает несколько связанных записей
>>> self.env['estate.property'].create({'name': 'house in shanghai'})
estate.property(2,)
>>> self.env['estate.property'].browse([2])
estate.property(2,)
>>> self.env['estate.property'].browse([2]).tag_ids
estate.property.tag()
>>> self.env['estate.property'].browse([2]).tag_ids = [(0, 0, {'name': 'tag5', 'color': 5}), (0, 0, {'name': 'tag6', 'color': 6}), (0, 0, {'name': 'tag7', 'color': 7})]
>>> self.env['estate.property'].browse([2]).tag_ids
estate.property.tag(5, 6, 7)

# Удалить записи, связанные со связью Поле
# (2, id, 0)
# Удалить запись с идентификатором id из набора записей, а затем удалить ее (из базы данных), могу быть тамcreate()серединаиспользовать
>>> self.env['estate.property'].browse([2]).tag_ids = [(2, 5, 0)]
2023-01-29 08:48:25,491 15984 INFO odoo odoo.models.unlink: User #1 deleted estate.property.tag records with IDs: [5]
>>> print( self.env['estate.property.tag'].browse([5]).exists())
estate.property.tag()
>>> if self.env['estate.property.tag'].browse([5]).exists():
...     print('exists record with id equal 5')
...
>>>

# Создать тестовые данные
>>> self.env['estate.property.tag'].create({'name': 'tag8', 'color': 8})
estate.property.tag(8,)
>>> self.env['estate.property.tag'].create({'name': 'tag9', 'color': 9})
estate.property.tag(9,)
>>> self.env['estate.property'].browse([2])
estate.property(2,)

# Заменить записи, связанные с отношением Поле
# (6, 0, ids) 
# Заменить все существующие записи на основе списка идентификаторов, Эквивалентно использованию команды (5, 0, 0), затем используйте команду (4, id, 0)。
>>> self.env['estate.property'].browse([2]).tag_ids
estate.property.tag(6, 7)
>>> self.env['estate.property'].browse([2]).tag_ids = [(6, 0 , [8, 9])]
>>> self.env['estate.property'].browse([2]).tag_ids
estate.property.tag(8, 9)
>>>

# Получить список записей Полеценить (связанные атрибуты записи ценить) через сопоставленные
>>> self.env['estate.property'].browse([2]).tag_ids.mapped('name')
['tag8', 'tag9']
>>> self.env['estate.property'].browse([2]).mapped('tag_ids')
estate.property.tag(8, 9)
>>> self.env['estate.property'].browse([2]).mapped('tag_ids').mapped('id')) 
[8, 9]
              

# search api приложение
# поиск домена
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)])
estate.property.tag(6, 7, 8, 9)

# компенсировать
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1)
estate.property.tag(7, 8, 9)

# Предел становится максимальным Количеством в рекордном наборе записей
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1, limit=2)
estate.property.tag(7, 8)

# станет сортировка записей в наборе записей
# порядок убывания
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1, limit=2, order = 'id desc')
estate.property.tag(8, 7)
# По возрастанию
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1, limit=2, order = 'id')
estate.property.tag(7, 8)
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1, limit=2, order = 'id asc')
estate.property.tag(7, 8)

# тольковозвращаться Количество записей
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], count=True)
4
# Используйте search_count API достигает эквивалентных эффектов
>>> self.env['estate.property.tag'].search_count(args=[('id', '>', 5)])
4

# поиск сочетание условий домена
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5),('color', '<', 8)])
estate.property.tag(6, 7)


# получать Записать (установить) информацию
# ids
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)]).ids
[6, 7, 8, 9]
# env
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)]).env
<odoo.api.Environment object at 0x0000020E31C80080>
# name_get api использовать
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)]).name_get()
[(6, 'tag6'), (7, 'tag7'), (8, 'tag8'), (9, 'tag9')]
# get_metadata api использовать
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)]).get_metadata()
[{'id': 6, 'create_uid': (1, 'OdooBot'), 'create_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'write_uid': (1, 'OdooBot'), 'write_date': datetime.datetime(2023, 1, 29, 8,41, 10, 551001), 'xmlid': False, 'noupdate': False}, {'id': 7, 'create_uid': (1, 'OdooBot'), 'create_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'write_uid': (1, 'OdooBot'), 'write_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'xmlid': False, 'noupdate': False}, {'id': 8, 'create_uid': (1, 'OdooBot'), 'create_date': datetime.datetime(2023,1, 29, 8, 41, 10, 551001), 'write_uid': (1, 'OdooBot'), 'write_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'xmlid': False, 'noupdate': False}, {'id': 9, 'create_uid': (1, 'OdooBot'), 'create_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'write_uid': (1, 'OdooBot'), 'write_date': datetime.datetime(2023, 1, 29, 8, 41, 10, 551001), 'xmlid': False, 'noupdate': False}]


# использовать read_group Реализуйте групповое чтение.
>>> self.env['estate.property.tag'].create({'name': 'tag10', 'color': 9})
estate.property.tag(10,)
>>> self.env['estate.property.tag'].read_group([], fields=['color'], groupby=['color'])
[{'color_count': 1, 'color': 6, '__domain': [('color', '=', 6)]}, {'color_count': 1, 'color': 7, '__domain': [('color', '=', 7)]}, {'color_count': 1, 'color': 8, '__domain': [('color', '=', 8)]}, {'color_count': 2, 'color': 9, '__domain': [('color', '=', 9)]}]


# Получить определение поля
>>> self.env['estate.property.tag'].fields_get(['name'])
{'name': {'type': 'char', 'change_default': False, 'company_dependent': False, 'depends': (), 'manual': False, 'readonly': False, 'required': True, 'searchable': True, 'sortable': True
, 'store': True, 'string': 'tag', 'translate': False, 'trim': True}}

# откат
>>> self.env.cr.rollback()
>>> self.env['estate.property.tag'].search(args=[('id', '>', 5)], offset=1, limit=2, order = 'id')
estate.property.tag()

# осуществлять sql
self.env.cr.execute('TRUNCATE TABLE estate_property_tag_test CASCADE;')
self.env.cr.commit()
# Сброс автоматически увеличивающегося идентификатора первичного ключа для1 (идентификатор первичного ключа каждой таблицы существует с именем для tableName_id_seq (в рейтинге)
self.env.cr.execute('ALTER SEQUENCE estate_property_tag_test_id_seq RESTART WITH 1;')
self.env.cr.commit()

>>> self.env['estate.property.tag'].create([{'name': 'tag1', 'color': 1}, {'name': 'tag2', 'color': 2}, {'name': 'tag3', 'color': 3}])
estate.property.tag(1, 2, 3)

# Пакетное обновлениеновый рекорд Полеценить #Если в наборе записей несколько записей, его невозможно передать. records.fieldName = Цельценить Внедрение пакетных обновлений
>>> self.env['estate.property.tag'].browse([1,3]).write({'color':1})  
True
>>> self.env['estate.property.tag'].browse([1,3]).mapped('color')
[1, 1]

# Изменение контекста набора записей запроса
>>> self.env['estate.property.tag'].browse([]).env.context
{'lang': 'en_US', 'tz': 'Europe/Brussels'}
>>> self.env['estate.property.tag'].with_context(is_sync=False).browse([]).env.context
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'is_sync': False}

# with_contextиsudo共存часизиспользовать Способ
>>> self.env['estate.property.tag'].with_context(is_sync=False).sudo().browse([]).env.context
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'is_sync': False}
>>> self.env['estate.property.tag'].sudo().with_context(is_sync=False).browse([]).env.context
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'is_sync': False}

# Изменить контекст записи при создании записи (подробнее новый запись(запись) также используется таким же образом)
# нравиться此,Вы можете переопределить метод createилиwrite соответствующей модели.,И получить целевой ключценить через self.env.context в методе,а потомосуществлять需求实现нуждаться采取из动делать,См. ниже
>>> self.env['estate.property.tag'].with_context(is_sync=False).create({'name': 'tag4', 'color': 4}).env.context
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'is_sync': False}


# удалить запись
>>> self.env['estate.property.tag'].search([])
estate.property.tag(1, 2, 3, 4)
>>> self.env['estate.property.tag'].search([('id', '>', 2)]).unlink()
2023-01-29 09:55:47,796 15984 INFO odoo odoo.models.unlink: User #1 deleted estate.property.tag records with IDs: [3, 4]
True

# Пройти набор записей
>>> for record_set in self. self.env['estate.property.tag.test'].search([]):
...     print(record_set)
...
estate.property.tag.test(1,)
estate.property.tag.test(2,)

Получить контекстный целевой ключ контекстаценить Пример

Язык кода:javascript
копировать
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from odoo import models, fields,api

class EstatePropertyTag(models.Model):
    _name = 'estate.property.tag'
    _description = 'estate property tag'
    _order = 'name'

    name = fields.Char(string='tag', required=True)
    color = fields.Integer(string='Color')


    @api.model
    def create(self, vals_list):
        res = super(EstatePropertyTag, self).create(vals_list)
        # Получить контекстный целевой ключценить
        if not self.env.context.get('is_sync', True):
            # do something you need
        return res

Эталонное соединение

https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/orm.html#

boy illustration
RasaGpt — платформа чат-ботов на основе Rasa и LLM.
boy illustration
Nomic Embed: воспроизводимая модель внедрения SOTA с открытым исходным кодом.
boy illustration
Улучшение YOLOv8: EMA основана на эффективном многомасштабном внимании, основанном на межпространственном обучении, и эффект лучше, чем у ECA, CBAM и CA. Малые цели имеют очевидные преимущества | ICASSP2023
boy illustration
Урок 1 серии Libtorch: Тензорная библиотека Silky C++
boy illustration
Руководство по локальному развертыванию Stable Diffusion: подробные шаги и анализ распространенных проблем
boy illustration
Полностью автоматический инструмент для работы с видео в один клик: VideoLingo
boy illustration
Улучшения оптимизации RT-DETR: облегченные улучшения магистрали | Support Paddle облегченный rtdetr-r18, rtdetr-r34, rtdetr-r50, rtdet
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | Деформируемое внимание с большим ядром (D-LKA Attention), большое ядро ​​​​свертки улучшает механизм внимания восприимчивых полей с различными функциями
boy illustration
Создано Datawhale: выпущено «Руководство по тонкой настройке развертывания большой модели GLM-4»!
boy illustration
7B превышает десятки миллиардов, aiXcoder-7B с открытым исходным кодом Пекинского университета — это самая мощная модель большого кода, лучший выбор для корпоративного развертывания.
boy illustration
Используйте модель Huggingface, чтобы заменить интерфейс внедрения OpenAI в китайской среде.
boy illustration
Оригинальные улучшения YOLOv8: несколько новых улучшений | Сохранение исходной информации — алгоритм отделяемой по глубине свертки (MDSConv) |
boy illustration
Второй пилот облачной разработки | Быстро поиграйте со средствами разработки на базе искусственного интеллекта
boy illustration
Бесшовная интеграция, мгновенный интеллект [1]: платформа больших моделей Dify-LLM, интеграция с нулевым кодированием и встраивание в сторонние системы, более 42 тысяч звезд, чтобы стать свидетелями эксклюзивных интеллектуальных решений.
boy illustration
Решенная Ошибка | Загрузка PyTorch медленная: TimeoutError: [Errno 110] При загрузке факела истекло время ожидания — Cat Head Tiger
boy illustration
Brother OCR, библиотека с открытым исходным кодом для Python, которая распознает коды проверки.
boy illustration
Новейшее подробное руководство по загрузке и использованию последней демонстрационной версии набора данных COCO.
boy illustration
Выпущен отчет о крупной модели финансовой отрасли за 2023 год | Полный текст включен в загрузку |
boy illustration
Обычные компьютеры также могут работать с большими моделями, и вы можете получить личного помощника с искусственным интеллектом за три шага | Руководство для начинающих по локальному развертыванию LLaMA-3
boy illustration
Одной статьи достаточно для анализа фактора транскрипции SCENIC на Python (4)
boy illustration
Бросая вызов ограничениям производительности небольших видеокарт, он научит вас запускать большие модели глубокого обучения с ограниченными ресурсами, а также предоставит полное руководство по оценке и эффективному использованию памяти графического процессора!
boy illustration
Команда Fudan NLP опубликовала 80-страничный обзор крупномасштабных модельных агентов, в котором в одной статье представлен обзор текущего состояния и будущего агентов ИИ.
boy illustration
[Эксклюзив] Вы должны знать о новой функции JetBrains 2024.1 «Полнострочное завершение кода», чтобы решить вашу путаницу!
boy illustration
Краткое изложение базовых знаний о регистрации изображений 1.0
boy illustration
Новейшее подробное руководство по установке и использованию библиотеки cv2 (OpenCV, opencv-python) в Python.
boy illustration
Легко создайте локальную базу знаний для крупных моделей на основе Ollama+AnythingLLM.
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание решения. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Одна статья поможет вам понять RAG (Retrival Enhanced Generation) | Введение в концепцию и теорию + практику работы с кодом (включая исходный код).
boy illustration
Эволюция архитектуры шлюза облачной разработки
boy illustration
Docker и Kubernetes [Разработка контейнерных приложений с помощью Python]