odoo17 | 模型视图继承

news2024/11/16 3:13:11

前言

Odoo的强大之处在于它的模块化。模块专门用于满足业务需求,但模块也可以彼此交互。这对于扩展现有模块的功能非常有用。例如,在我们的房地产场景中,我们希望在常规用户视图中直接显示销售人员的属性列表。

但是在讨论特定的Odoo模块继承之前,让我们看看如何更改标准CRUD(创建、检索、更新或删除)方法的行为。

Python 继承

目标

  • 设定不能删除非新建或已取消的属性。
    在这里插入图片描述
  • 创建产品/服务后,属性状态应更改为“已收到产品/服务”
  • 不能创建一个比现有报价更低的报价
    在这里插入图片描述
    在我们的房地产模块中,我们不需要开发任何特定的东西来执行标准的CRUD操作。Odoo框架提供了完成这些任务所需的工具。事实上,由于经典的Python继承,这些操作已经包含在我们的模型中:
from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    ...

我们的类TestModel继承自提供create()、read()、write()unlink()功能的models.Model

这些方法(以及Model类上定义的任何其他方法)可以扩展以添加特定的业务逻辑:

from odoo import fields, models

class TestModel(models.Model):
    _name = "test_model"
    _description = "Test Model"

    ...

    @api.model
    def create(self, vals):
        # 做一些业务逻辑,修改值…
        ...
        # 然后调用super来执行父方法
        return super().create(vals)

装饰器model()对于create()方法是必需的,因为记录集本身的内容与创建上下文无关,但对于其他CRUD方法则不是必需的。

同样重要的是要注意,尽管我们可以直接覆盖**unlink()方法,但您几乎总是希望用ondelete()装饰器来编写一个新方法。带有此装饰符的方法将在unlink()期间被调用,从而避免了当unlink()**被直接覆盖时卸载模型模块时可能出现的一些问题。

Python 3中,super()等价于super(TestModel, self)。当您需要使用修改后的记录集调用父方法时,后者可能是必需的。

注意

总是调用super()以避免中断流程是非常重要的。只有一些非常特殊的情况下你用调用super()。

确保始终返回与父方法一致的数据。例如,如果父方法返回dict(),则重写也必须返回dict()。

模型继承

在我们的房地产模块中,我们希望显示与销售人员相关的房地产列表 直接在“设置”/“用户和公司”/“用户”窗体视图中。为此,我们需要将一个字段添加到 模型并调整其视图以显示它。res.users

Odoo提供了两种继承机制,以模块化方式扩展现有模型。

第一种继承机制允许模块通过以下方式修改另一个模块中定义模型的行为

  • 向模型添加字段,

  • 覆盖模型中字段的定义,

  • 向模型添加约束,

  • 向模型添加方法,

  • 重写模型中的现有方法。

第二种继承机制(委托)允许模型的每个记录链接到父模型的记录,并提供对该父记录字段的透明访问。

在这里插入图片描述

在Odoo中,第一种机制是目前使用最多的。在我们的示例中,我们希望向现有模型添加一个字段,这意味着我们将使用第一种机制。例如:

from odoo import fields, models

class InheritedModel(models.Model):
    _inherit = "inherited.model"

    new_field = fields.Char(string="New Field")

可以在此处找到向模型添加两个字段的实际示例。

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import models, fields, api, _


class AccountMove(models.Model):
    _inherit = 'account.move'

    def _post(self, soft=True):
        vendor_bill_service = self.env.ref('account_fleet.data_fleet_service_type_vendor_bill', raise_if_not_found=False)
        if not vendor_bill_service:
            return super()._post(soft)

        val_list = []
        log_list = []
        not_posted_before = self.filtered(lambda r: not r.posted_before)
        posted = super()._post(soft)  # We need the move name to be set, but we also need to know which move are posted for the first time.
        for line in (not_posted_before & posted).line_ids.filtered(lambda ml: ml.vehicle_id):
            val = {
                'service_type_id': vendor_bill_service.id,
                'vehicle_id': line.vehicle_id.id,
                'amount': line.price_subtotal,
                'vendor_id': line.partner_id.id,
                'description': line.name,
            }
            log = _('Service Vendor Bill: <a href=# data-oe-model=account.move data-oe-id={move_id}>{move_name}</a>').format(
                move_id=line.move_id.id,
                move_name=line.move_id.name,
            )
            val_list.append(val)
            log_list.append(log)
        log_service_ids = self.env['fleet.vehicle.log.services'].create(val_list)
        for log_service_id, log in zip(log_service_ids, log_list):
            log_service_id.message_post(body=log)
        return posted


class AccountMoveLine(models.Model):
    _inherit = 'account.move.line'

    vehicle_id = fields.Many2one('fleet.vehicle', string='Vehicle')
    need_vehicle = fields.Boolean(compute='_compute_need_vehicle',
        help="Technical field to decide whether the vehicle_id field is editable")

    def _compute_need_vehicle(self):
        self.need_vehicle = False

按照惯例,每个继承的模型都在自己的Python文件中定义。在我们的例子中,它将是models/inherited_model.py。

视图继承

目标

  • 链接到销售人员的可用属性列表应显示在其用户窗体视图中
    在这里插入图片描述
    Odoo不是对现有视图进行修改(通过覆盖它们),而是提供视图继承,其中子“扩展”视图应用于根视图之上。这些扩展既可以添加也可以从父视图删除内容。

扩展视图使用 inherit_id 字段引用其父视图。与其单个视图不同,其 arch 字段包含多个 xpath 元素,用于选择和更改其父视图的内容

<record id="inherited_model_view_form" model="ir.ui.view">
    <field name="name">inherited.model.form.inherit.test</field>
    <field name="model">inherited.model</field>
    <field name="inherit_id" ref="inherited.inherited_model_view_form"/>
    <field name="arch" type="xml">
        <!-- find field description and add the field
             new_field after it -->
        <xpath expr="//field[@name='description']" position="after">
          <field name="new_field"/>
        </xpath>
    </field>
</record>

expr 表达式

一个XPath表达式,用于选择父视图中的一个元素。如果它没有匹配任何元素或匹配多个元素,则引发错误

position

应用于匹配元素的运算:

inside 在…内

将xpath的body附加到匹配元素的末尾

replace 代替

用xpath的body替换匹配的元素,将新body中出现的任何$0节点替换为原始元素

before 之前

将xpath的body作为同级插入到匹配的元素之前

after 之后

将xpath的body作为匹配元素之后的同级元素插入

attributes 属性,特征

使用XPath主体中的特殊属性元素更改匹配元素的属性

当匹配单个元素时,可以直接在要查找的元素上设置position属性。下面的两个继承具有相同的结果。

<xpath expr="//field[@name='description']" position="after">
    <field name="idea_ids" />
</xpath>

<field name="description" position="after">
    <field name="idea_ids" />
</field>

可以在这里找到一个视图继承扩展的示例。

<?xml version='1.0' encoding='utf-8'?>
<odoo>
    <record id="view_move_form" model="ir.ui.view">
        <field name="name">account.move.form</field>
        <field name="model">account.move</field>
        <field name="inherit_id" ref="account.view_move_form"/>
        <field name="arch" type="xml">
            <xpath expr="//field[@name='line_ids']//field[@name='account_id']" position="after">
                <field name='need_vehicle' invisible='1'/>
                <field name='vehicle_id' attrs="{'required': [('need_vehicle', '=', True), ('parent.move_type', '=', 'in_invoice')], 'column_invisible': [('parent.move_type', '!=', 'in_invoice')]}" optional='hidden'/>
            </xpath>
            <xpath expr="//field[@name='invoice_line_ids']//field[@name='account_id']" position="after">
                <field name='need_vehicle' invisible='1'/>
                <field name='vehicle_id' attrs="{'required': [('need_vehicle', '=', True), ('parent.move_type', '=', 'in_invoice')], 'column_invisible': [('parent.move_type', '!=', 'in_invoice')]}" optional='hidden'/>
            </xpath>
        </field>
    </record>
</odoo>

在下一章中,我们将学习如何 与其他模块交互。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1364941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 开源扫雷游戏 JMine 发布介绍视频

Java 开源扫雷游戏 JMine 发布介绍视频 Java 开源扫雷游戏 JMine 是笔者开发的基于 Swing 的 Java 扫雷游戏&#xff0c;现已发布介绍视频。视频请见&#xff1a;https://www.bilibili.com/video/BV1Qe411m7qM/ JMine 比较重视的还原了微软的扫雷游戏。在算法设计中&#xff…

【EAI 004】LLM+P:借助LLM和PDDL赋予机器人最优规划能力

论文标题&#xff1a;LLMP: Empowering Large Language Models with Optimal Planning Proficiency 论文作者&#xff1a;Bo Liu, Yuqian Jiang, Xiaohan Zhang, Qiang Liu, Shiqi Zhang, Joydeep Biswas, Peter Stone 作者单位&#xff1a;Department of Computer Science, Th…

WorkPlus Meet打造高质量的视频会议体验,助力实时远程协作

在全球化的商业环境中&#xff0c;远程协作和在线会议成为了企业高效工作的关键。作为一款高质量的视频会议软件&#xff0c;WorkPlus Meet以其卓越的性能和创新的功能&#xff0c;成为企业实时远程协作的首选。 WorkPlus Meet打造了高质量的视频会议体验&#xff0c;为企业提供…

Transformer - Attention is all you need 论文阅读

虽然是跑路来NLP&#xff0c;但是还是立flag说要做个project&#xff0c;结果kaggle上的入门project给的例子用的是BERT&#xff0c;还提到这一方法属于transformer&#xff0c;所以大概率读完这一篇之后&#xff0c;会再看BERT的论文这个样子。 在李宏毅的NLP课程中多次提到了…

vue使用elementui 的 table且自定义某列表头时,添加的点击事件和自带的筛选功能有类似冒泡行为

element 自带的table 需求&#xff1a;在时间这一列的筛选按钮旁边添加一个批量修改按钮问题&#xff1a;如果不加排序这个属性&#xff0c;那么表格自带的筛选和新加的批量筛选点击事件会冲突&#xff08;冒泡事件&#xff09;解决方法&#xff1a;在该列添加sortable属性&…

【IDEA】 解决在idea中连接 Mysql8.0,驱动无法下载问题

本篇继【idea】解决sprintboot项目创建遇到的问题2-CSDN博客 目录 一、Failed to download https://download.jetbrains.com/idea/jdbc-drivers/MySQL/8/LICENSE.txt:Remote host terminated the handshake 二、no dirver files provided com.mysql.cj.jdbc.Driver 三、Serv…

[蓝桥杯学习] ST表

RMQ问题 ST 表 用状态 s[i][j] 记录区间长度为 2^j 的长度的区间的最大值 所以状态转移方程就是 st[i][j] max( st[i][j-1] , st[i(1 << (j-1))][j-1] ) 注意状态转移的方向&#xff0c;保证区间合法性&#xff08;i2^j 不能超过数组大小&#xff09; 写完这些后&am…

Linux之Ubuntu环境Jenkins部署前端项目

今天分享Ubuntu环境Jenkins部署前端vue项目 一、插件安装 1、前端项目依赖nodejs&#xff0c;需要安装相关插件 点击插件管理&#xff0c;输入node模糊查询 选择NodeJS安装 安装成功 2、配置nodejs 点击后进入 点击新增 NodeJS 配置脚手架类型&#xff1a;如果不填 默认npm …

软件测试|Linux下Python安装配置指南

在Linux中安装Python是一个简单而且重要的过程&#xff0c;因为Python是一种广泛使用的编程语言&#xff0c;许多系统工具和应用都依赖于它。在本文中&#xff0c;我将详细介绍如何在Linux系统中安装Python。 请注意&#xff0c;在本文中&#xff0c;我将以Centos为例&#xf…

一键了解获取网页requests方式

目录 一、爬虫原理&#xff1a; 二、安装&#xff1a; 测试&#xff1a; 三、文件的操作 方式一 方式二: 方式三 四、认识User-Agent 4.1、为什么用User-Agent&#xff1a; 步骤&#xff1a; 五、请求方式 5.1、get 5.2、post 六、爬出有中国关键字页面案例 一、爬…

【两阶段鲁棒】计及需求响应的多能互补微网两阶段鲁棒优化matlab

目录 1 主要内容 算例模型 目标函数 第一阶段 第二阶段 求解流程图 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序参考文献《多能互补微网两阶段鲁棒优化调度研究》&#xff0c;在考虑风光不确定集的基础上提出采用计及DR响应的多能互补微网两阶段鲁棒备用调度模…

Android WiFi 连接

Android WiFi 连接 1、设置中WiFi显示2、WiFi 连接流程2.1 获取PrimaryClientModeManager2.2 ClientModeImpl状态机ConnectableState2.3 ISupplicantStaNetworkCallback 回调监听 3、 简要时序图4、原生低层驱动5、关键日志 1、设置中WiFi显示 Android WiFi基础概览 packages/a…

RabbitMQ(九)死信队列

目录 一、简介1.1 定义1.2 何时进入死信队列&#xff1f;1.3 死信消息的变化1.4 死信队列的应用场景1.5 死信消息的生命周期 二、代码实现2.1 死信队列的配置步骤2.2 配置类2.3 配置文件2.4 生产者2.5 业务消费者2.6 死信消费者2.7 测试结果 三、总结 RabbitMQ 是流行的开源消息…

MYSQL InnoDB引擎

逻辑存储结构 架构 内存架构 磁盘结构 后台线程 事务原理 redolog undo log MVCC 基本概念 实现原理 隐藏字段 undo log readview

学习使用layPage, 多功能JS分页组件/插件的方法

学习使用layPage, 多功能JS分页组件/插件的方法 效果图分页代码 效果图 点击查看链接 分页代码 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>Layui</title><meta name"renderer" content"we…

用队列实现栈oj题——225

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;LeetCode刷题|数据结构|Linux 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 题目要求&#xff1a;实现 MyStack 类&#xff1a;注意&#xff1a;示例&#xff1a;解释&#xff1a;提示&#xff1a; 解题核心数据结构的定义…

通信触发流程

该示例方案主要介绍如何通过建立的Modbus或TCP通信来实现触发方案、协议解析、发送事件和以及响应配置等功能。 需求&#xff1a;使用Modbus通信触发指定流程运行。 搭建思路&#xff1a;在接收事件中使用协议组装&#xff0c;比较规则选择上升沿&#xff0c;当接收到的值从其…

如何成为一名高级UI设计师,UI设计与交互动效进阶教学

一、教程描述 本套教程从基础学习到案例实践教学&#xff0c;涵盖了设计师所需的全部知识和实战技术&#xff0c;比如&#xff0c;品牌形象设计&#xff0c;企业视觉识别系统VIS&#xff0c;标志logo提案设计&#xff0c;banner运营视觉设计&#xff0c;字体搭配使用&#xff…

学习笔记 | Kafka

一、概述 定义 1、Kafka传统定义&#xff1a;Kafka 是一个分布式的基于 发布/订阅模式 的消息队列&#xff08;Message Queue&#xff09; &#xff0c;主要应用与大数据实时处理领域。 2、发布/订阅&#xff1a;消息的发送者不会将消息直接发送给特定的订阅者&#xff0c;而…

企业网盘全方位解读:热门云存储工具的优势与适用场景

企业网盘无疑是当下最热门的企业协同工具。什么是企业网盘&#xff1f;企业网盘与个人网盘又有什么不同呢&#xff1f;一文全方位解读企业网盘这一热门云存储工具。 什么是企业网盘 企业网盘为企业级文件存储、管理与共享平台&#xff0c;企业团队可以在企业网盘中存储企业文…