├── setting-up ├── email-gateway.md ├── deploying-content-delivery-networks.md ├── community-enterprise.md ├── updating-odoo-installation.md ├── deploying-odoo.md └── installing-odoo.md ├── reference ├── security-odoo.md ├── module-manifests.md ├── mobile-javascript.md ├── translating-modules.md ├── web-controllers.md ├── qweb-reports.md ├── actions.md ├── command-line-interface-odoo-bin.md ├── qweb.md ├── javascript-cheatsheet.md └── testing-odoo.md ├── README.md ├── tutorials ├── profiling-odoo-code.md └── theme-tutorial.md └── web-services ├── creating-localization.md ├── database-upgrade.md └── in-app-purchase.md /setting-up/email-gateway.md: -------------------------------------------------------------------------------- 1 | # Odoo email 网关 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | Odoo邮件网关允许我们在Odoo中直接注入所有已接收邮件。其原理直截了当:你的SMTP服务为每个新新收邮件执行“mailgate”脚本。该脚本通过XML-RPC处理与Odoo数据库的连接,并通过MailThread.message_process()功能发送邮件。 6 | 7 | ## 前提条件 8 | 9 | - 对Odoo数据库的管理员权限。 10 | - 自己的邮件服务器,如 Postfix 或 Exim。 11 | - 有关如何配置邮件服务器的技术知识。 12 | 13 | ## Postfix篇 14 | 15 | 在alias配置 (/etc/aliases)中配置: 16 | 17 | ``` 18 | email@address: "|/odoo-directory/addons/mail/static/scripts/odoo-mailgate.py -d -u -p " 19 | ``` 20 | 21 | 郑源 - `Postfix` - `Postfix aliases` - `Postfix virtual` 22 | 23 | ## Exim篇 24 | 25 | ``` 26 | *: |/odoo-directory/addons/mail/static/scripts/odoo-mailgate.py -d -u -p 27 | ``` 28 | 29 | 资源 - `Exim` 30 | 31 | 如果你可以访问/管理自己的邮件服务器,使用`inbound messages`. -------------------------------------------------------------------------------- /setting-up/deploying-content-delivery-networks.md: -------------------------------------------------------------------------------- 1 | # 通过 CDN 进行部署 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](https://alanhou.org/odoo-13-developer-documentation/)系列文章 4 | 5 | ## 通过[KeyCDN](https://www.keycdn.com/)进行部署 6 | 7 | 本文档将指导你为Odoo网站配置一个 [KeyCDN](https://www.keycdn.com/) 账户。 8 | 9 | ### 第1步:在KeyCDN仪表盘中创建一个pull 区 10 | 11 | ![img](https://www.odoo.com/documentation/13.0/_images/keycdn_create_a_pull_zone.png)创建该区时,在高级功能子菜单中启用CORS选择。 (更多参见后述内容) 12 | 13 | ![img](https://www.odoo.com/documentation/13.0/_images/keycdn_enable_CORS.png)一旦完成后,需要等待片刻,此时[KeyCDN](https://www.keycdn.com/)会爬取你的网站。 14 | 15 | ![img](https://www.odoo.com/documentation/13.0/_images/keycdn_progressbar.png) 16 | 17 | 会为你的Zone生成一个新的 URL,本例中链接为 `http://pulltest-b49.kxcdn.com` 18 | 19 | ### 第2步:使用你的zone 配置odoo实例 20 | 21 | 在Odoo后台中,进入到网站设置(Website Settings)菜单,然后启用CDN并复制/拷贝你的zone URL到 CDN Base URL字段中。该字段仅在启用了开发者模式之后才可见并可配置。 22 | 23 | ![img](https://www.odoo.com/documentation/13.0/_images/odoo_cdn_base_url.png)现在你的网站会对匹配CDN过滤器正则表达式的资源使用 CDN。 24 | 25 | 可以查看网站的HTML源码来确定是否正确地进行了CDN集成。 26 | 27 | ![img](https://www.odoo.com/documentation/13.0/_images/odoo_check_your_html.png) 28 | 29 | ### 为什么要激活CORS? 30 | 31 | 在一些浏览器(编写本文档时有Firefox 和 Chrome )的安全限制中会防止远程链接的CSS文件获取该外部服务器上的相对资源。 32 | 33 | 如未在CDN区中启用 CORS选项,默认Odoo网站上最明显的问题是缺少 font-awesome图标,因为在 font-awesome的CSS中声明字体文件无法通过远程服务器进行加载。 34 | 35 | 以下是在这种情况下首页的样子: 36 | 37 | ![img](https://www.odoo.com/documentation/13.0/_images/odoo_font_file_not_loaded.png)一条安全错误信息会出现在浏览器的控制台中: 38 | 39 | ![img](https://www.odoo.com/documentation/13.0/_images/odoo_security_message.png)在 CDN 中启用CORS选择可解决这一问题。 -------------------------------------------------------------------------------- /reference/security-odoo.md: -------------------------------------------------------------------------------- 1 | # Odoo中的安全 2 | 3 | - 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | 除手动通过自定义模式管理权限外,Odoo还提供了两种数据驱动的机制来管理或限制对数据的访问。 6 | 7 | 这两种机制都通过**组**来与具体用户相关联:一个用户可属于多个组,安全机制与组进行关联,进而应用对用户应用安全机制。 8 | 9 | 10 | 11 | ## 访问控制 12 | 13 | 由`ir.model.access`记录进行管理, 定义对整个模型的访问。 14 | 15 | 每个访问控制有其授予权限的模型,授予的权限及可选用户组。 16 | 17 | 访问控制是附加的,对于一个给定模型用户拥有所有授予其所属组的权限,如用记属于一个允许写入的组及一个允许删除的组,那么用记就同时拥有写入和删除的权限。 18 | 19 | 如未指定组,访问控制应用于所有用户,否则它仅应用于给定组的成员。 20 | 21 | 可用的权限有创建(`perm_create`)、搜索和读取 (`perm_read`)、更新已有记录s (`perm_write`) 及删除已有记录(`perm_unlink`) 22 | 23 | 24 | 25 | ## 记录规则 26 | 27 | 记录规则是必须满足所允许操作(创建、读取、更新或删除)记录的条件。它在应用了访问控制后逐记录应用。 28 | 29 | 记录规则有: 30 | 31 | - 其所应用的模型 32 | - 一组它所应用的权限 (例如,如果设置了 `perm_read`,规则仅在读取记录时进行检查) 33 | - 一组规则所应用的用户组,如未指定组则是**全局**规则 34 | - 用于检查给定记录是否匹配规则(并可访问)或不匹配(不可访问)的[作用域](https://alanhou.org/odoo-13-orm-api/l#reference-orm-domains) 。作用域通过两个上下文变量进行运行: `user` 是当前用户的记录,`time` 是 [time模块](https://docs.python.org/2/library/time.html) 35 | 36 | 全局赍是和组规则 (限制给定用记的规则 vs.应用所有用户的组) 的使用差别很大: 37 | 38 | - 使用局规则做减法,它们必须匹配可访问的记录 39 | - 组规则做加法,如匹配其中任一规则 (且匹配所有全局规则)则记录可进行访问 40 | 41 | 这表示第一个**组规则**限制访问,但其它的**组规则**对进行扩展,而**全局规则**仅限制访问 (或不起任何作用)。 42 | 43 | ### ⚠️警告 44 | 45 | 记录规则对管理员用户不起作用 46 | 47 | 48 | 49 | ## 字段权限 50 | 51 | 7.0版本中新增。 52 | 53 | ORM [`字段`](https://alanhou.org/odoo-13-orm-api/#odoo.fields.Field)可带有 `groups`属性来提供一个组列表 (作为一个[外部标识符](https://www.odoo.com/documentation/13.0/glossary.html#term-external-identifiers)的逗号分隔字符串)。 54 | 55 | 如当前用记不在所列举的组中,将无法访问该字段: 56 | 57 | - 受限的字段自动从所请求的视图中删除 58 | - 受限的字段从 [`fields_get()`](https://alanhou.org/odoo-13-orm-api/#odoo.models.Model.fields_get) 响应中进行删除 59 | - 尝试 (显式地) 从受限的字段中读取或进行写入会导致访问错误 -------------------------------------------------------------------------------- /setting-up/community-enterprise.md: -------------------------------------------------------------------------------- 1 | # 社区版转企业版 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | 根据当前的安装方式,有多种升级社区版的方法。各种情况下的基本指导思想是: 6 | 7 | - 备份社区版数据库![img](https://www.odoo.com/documentation/13.0/_images/db_manager.png) 8 | - 关闭服务 9 | - 安装web_enterprise模块 10 | - 重启服务 11 | - 输入Odoo企业版订阅码 12 | 13 | ![img](https://www.odoo.com/documentation/13.0/_images/enterprise_code.png) 14 | 15 | ## 在Linux中使用安装包 16 | 17 | - 备份社区版数据库 18 | 19 | - 停止odoo服务 20 | 21 | ``` 22 | $ sudo service odoo stop 23 | ``` 24 | 25 | - 安装企业版 .deb (应该在社区安装包之上安装) 26 | 27 | ``` 28 | $ sudo dpkg -i 29 | ``` 30 | 31 | - 使用如下命令更新数据库为企业版安装包 32 | 33 | ``` 34 | $ python3 /usr/bin/odoo-bin -d -i web_enterprise --stop-after-init 35 | ``` 36 | 37 | - 应当能够使用常规的认证方式连接到 Odoo企业版实例。然后你可以通过在表单输入框中输入邮件中所收到的订阅码将数据库与你的Odoo企业版订阅进行关联。 38 | 39 | ## 在Linux中使用源代码 40 | 41 | 有很多种使用源码启动服务器的方式,你可能已有自己的偏好。可以将下面部分调整为你自己的常规工作流。 42 | 43 | - 关闭你的服务 44 | 45 | - 备份社区版数据库 46 | 47 | - 更新启动命令中的 `--addons-path` 参数 (参见 [源码安装](https://alanhou.org/odoo-13-installing-odoo/#setup-install-source)) 48 | 49 | - 通过使用如下命令安装 web_enterprise 模块 50 | 51 | ``` 52 | $ -d -i web_enterprise --stop-after-init 53 | ``` 54 | 55 | 根据数据库的大小不同,可能会花费一些时间。 56 | 57 | - 使用第3点中更新的addons路径重新启动服务。 此时应该可以连接到实例。可以通过在表单输入框中输入邮件中所收到的订阅码将数据库与你的Odoo企业版订阅进行关联。 58 | 59 | ## 在Windows上 60 | 61 | - 备份社区版数据库 62 | 63 | - 卸载Odoo 社区版 (使用安装文件夹中的 Uninstall可执行文件) - PostgreSQL将保持已安装状态![img](https://www.odoo.com/documentation/13.0/_images/windows_uninstall.png) 64 | 65 | - 启动 Odoo企业版安装器并按照常规步骤执行。在选择安装路径时,可以设置社区版软件的文件夹(这个文件夹中还包含PostgreSQL软件 )。 在安装的最后取消勾选 `Start Odoo` ![img](https://www.odoo.com/documentation/13.0/_images/windows_setup.png) 66 | 67 | - 使用命令行窗口,使用下面的命令(通过服务的子文件夹中的Odoo 安装路径)更新Odoo数据库 68 | 69 | ``` 70 | $ odoo.exe -d -i web_enterprise --stop-after-init 71 | ``` 72 | 73 | - 无需手动启动服务,服务已运行。这时应该可以使用常规的认证方式连接到Odoo企业版实例了。然后可以通过在表单输入框中输入邮件中所收到的订阅码将数据库与你的Odoo企业版订阅进行关联。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Odoo 官方文档之开发者文档 2 | 3 | ## Tutorials 4 | 5 | - [主题教程](tutorials/theme-tutorial.md) 6 | - [建造网站](tutorials/building-website.md) 7 | - [构建模块](tutorials/building-module.md) 8 | - [自定义网页客户端](tutorials/customizing-web-client.md) 9 | - [Odoo 代码性能测试](tutorials/profiling-odoo-code.md) 10 | 11 | ## Web Services 12 | 13 | - [外部API](https://alanhou.org/odoo-13-external-api/) 14 | - [应用内购买](https://alanhou.org/odoo-13-in-app-purchase/) 15 | - [数据库升级](https://alanhou.org/odoo-13-database-upgrade/) 16 | - [会计本地化](https://alanhou.org/odoo-13-creating-localization/) 17 | 18 | ## Setting Up 19 | 20 | - [安装Odoo](https://alanhou.org/odoo-13-installing-odoo/) 21 | - [部署Odoo](https://alanhou.org/odoo-13-deploying-odoo/) 22 | - [更新Odoo安装版本](https://alanhou.org/odoo-13-updating-odoo-installation/) 23 | - [使用 CDN(内容分发网络)部署](https://alanhou.org/odoo13-deploying-content-delivery-networks/) 24 | - [社区版转企业版](https://alanhou.org/odoo-13-community-enterprise/) 25 | - [Odoo email 网关](https://alanhou.org/odoo-13-email-gateway/) 26 | 27 | ## Reference 28 | 29 | - [ORM API](https://alanhou.org/odoo-13-orm-api/) 30 | - [数据文件](https://alanhou.org/odoo-13-data-files/) 31 | - [动作](https://alanhou.org/odoo-13-actions/) 32 | - [视图](https://alanhou.org/odoo-13-views/) 33 | - [模块声明文件](https://alanhou.org/odoo-13-module-manifests/) 34 | - [命令行接口:odoo-bin](https://alanhou.org/odoo-13-command-line-interface-odoo-bin/) 35 | - [Odoo中的安全](https://alanhou.org/odoo-13-security-odoo/) 36 | - [测试Odoo](https://alanhou.org/odoo-13-testing-odoo/) 37 | - [网页控制器](https://alanhou.org/odoo-13-web-controllers/) 38 | - [QWeb](https://alanhou.org/odoo-13-qweb/) 39 | - [Javascript速查](https://alanhou.org/odoo-13-javascript-cheatsheet/) 40 | - [Javascript手册](https://alanhou.org/odoo-13-javascript-reference/) 41 | - [模块翻译](https://alanhou.org/odoo-13-translating-modules/) 42 | - [QWeb报表](https://alanhou.org/odoo-13-qweb-reports/) 43 | - [Mixins和有用的类](https://alanhou.org/odoo-13-mixins-classes/) 44 | - [Odoo代码指南](https://alanhou.org/odoo-13-odoo-guidelines/) 45 | - [移动端JavaScript](https://alanhou.org/odoo-13-mobile-javascript/) -------------------------------------------------------------------------------- /setting-up/updating-odoo-installation.md: -------------------------------------------------------------------------------- 1 | # 更新Odoo安装版本 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | ## 引言 6 | 7 | 为获取最新的提升、安全修复、漏洞修正及性能提升,可能会需要不时更新Odoo的软件。 8 | 9 | 本指南仅用于在自己的托管基础设置上使用Odoo的情况。如果你使用的是Odoo的某种云方案,会自动为你执行升级操作。 10 | 11 | 与软件升级相关的用词通常很让人困惑,以下是一些基本定义: 12 | 13 | - 更新(Odoo软件) 14 | 15 | 代指获取当前 Odoo 版本的最新修订版的过程。例如,更新你的Odoo Enterprise 13.0到最新修订版。这并不会直接引起对Odoo数据库内容的修改,并且可通过重装此前修订版的源代码来进行取消。 16 | 17 | - 升级 (Odoo数据库) 18 | 19 | 表示一个复杂的数据处理操作,其中数据库的内容和结构会进行永久改变来让其与新的Odoo发行版进行兼容。这种操作是不可逆的并且通常是在你决定要切换到更新的 Odoo 发行版时由Odoo的[数据库升级服务](https://upgrade.odoo.com/)来完成。曾经这一过程也称之为“迁移”,因为它包含着在数据库内部移动数据,虽然数据库在升级后可能依然处于同一个物理空间内。 20 | 21 | 本文描述需要*更新*Odoo软件为最新版本所需要的通常步骤。如果想要了解有关升级数据库的更多信息,请访问 [Odoo升级页面 ](https://upgrade.odoo.com/)。 22 | 23 | ## 概述 24 | 25 | 更新Odoo仅需通过对当前所安装的Odoo 进行最新版本的最新安装即可。这样只要你不卸载PostgreSQL(Odoo所带的数据库引擎)会保留所有数据不进行任何修改。 26 | 27 | 升级的主要指南逻辑上参考 [安装指南](https://alanhou.org/odoo-13-installing-odoo/),其中讲解了最常见的安装方法。 28 | 29 | 升级也最宜由最初部署Odoo的人员实施,因为其流程非常相近。 30 | 31 | 我们经常推荐下载完整的最新Odoo版本,而不单是手动应用补丁,如安全公告中所发布的补丁。这些补丁通常是提供给那些高度客制化的安装,或那样希望在测试完整升级前临时测试最小化修改的技术人员。 32 | 33 | ## 第1步: 下载已更新的Odoo版本 34 | 35 | 主要下载页面是 https://www.odoo.com/page/download。如果看到下载 Odoo 企业版的“Buy”链接,请务必使用与 Odoo 企业版订阅相关联的账号登录到Odoo.com上。 36 | 37 | 此外,你可以使用在Odoo企业版购买确认邮件中所包含的独立下载链接 。 38 | 39 | 如果通过Github进行的安装则无需下载已升级的版本 (参照下面部分) 40 | 41 | ## 第2步: 进行数据库备份 42 | 43 | 升级的流程非常安全且不修改数据。但还是推荐最好在对软件执行修改前进行完整的数据库备份,并保存在另一台电脑上一个安全的地方。 44 | 45 | 如果未禁用数据库管理界面 (在 [这里](#security)查看为什么应禁用),,则可以使用它 (在数据库选择界面的下方链接) 来下载数据库备份。如果进行了禁用,使用和日常备份桢的流程。 46 | 47 | ## 第3步: 安装更新版本 48 | 49 | 选择与当前安装相匹配的方法: 50 | 51 | ### 包安装器 52 | 53 | 如果使用从官网下载的安装包进行的Odoo安装(推荐方法),升级非常之简单。你只需要下载与系统相对应的安装包(参见第1步)并在服务器上进行安装即可。它会按日进行更新并包含最新的漏洞修复。通常,你只需在当前软件的顶部双击包来进行安装。在安装该包之后,确保要重启Odoo服务或在准备妥当的情况下重启服务器。 54 | 55 | ### 源码安装(Tarball) 56 | 57 | 如果你最初是通过“tarball”版本(源码存档)进行的Odoo安装,则需替换安装路径为新的版本。首先从Odoo.com下载最新的 tarball。它会按日进行更新并包含最新的漏洞修复(参见第1步)。在下载完包之后,将其解压到服务器的临时位置中。 58 | 59 | 你将获取到一个带有源码版本标记的文件夹,例如“odoo-13.0+e.20190719”,其中包含一个“odoo.egg-info”文件夹并实际源码文件夹名为 “odoo” (Odoo 10及此后版本)或针对老版本名为“openerp”。可以忽略这个odoo.egg-info文件夹。定位到当前软件部署所在的文件夹,交将其替换为你刚刚解压的新的“odoo” 或 “openerp”文件夹。 60 | 61 | 确保要匹配文件夹布局,例如在新源码中所含的“addons”文件夹应与之前的路径完全一致。其次注意任意你在老文件夹中手动拷贝或修改的配置文件,将它们拷贝到亲的文件夹中。最后,重启Odoo服务或在准备妥当的情况下重启服务器。 62 | 63 | ### 源码安装(Github) 64 | 65 | 如果最初是通过对Github上的官方仓库进行完整克隆来完成安装的话,更新过程仅需你通过git拉取最新的源代码。进入各仓库的路径(主Odoo仓库,及企业版仓库),并运行如下命令: 66 | 67 | ``` 68 | git fetch 69 | git rebase --autostash 70 | ``` 71 | 72 | 如果在本地编辑过Odoo源代码的话最后那条命令可能会碰到源码冲突。错误消息会给出冲突的文件列表,你需要手动处理这些冲突,通过对它们进行编辑来决定保留哪一部分的代码。 73 | 74 | 而如果你倾向于抛弃所有的冲突修改,恢复为官方版本的话,可以使用如下命令: 75 | 76 | ``` 77 | git reset --hard 78 | ``` 79 | 80 | 最后,重启Odoo服务或重启服务器,一切应当会就绪了。 81 | 82 | ### Docker 83 | 84 | 请参见我们的 [Docker镜像文档](https://hub.docker.com/_/odoo/)了解最体的升级指南。 -------------------------------------------------------------------------------- /reference/module-manifests.md: -------------------------------------------------------------------------------- 1 | # 模块声明文件 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](https://alanhou.org/odoo-13-developer-documentation/)系列文章 4 | 5 | ## 声明 6 | 7 | 声明文件用于声明python包为Odoo模块并指定模块元数据信息。 8 | 9 | 它是一个名为`__manifest__.py`的文件,包含一个 Python字典,其中每个键指定模块元数据单元。 10 | 11 | ``` 12 | { 13 | 'name': "A Module", 14 | 'version': '1.0', 15 | 'depends': ['base'], 16 | 'author': "Author Name", 17 | 'category': 'Category', 18 | 'description': """ 19 | Description text 20 | """, 21 | # data files always loaded at installation 22 | 'data': [ 23 | 'views/mymodule_view.xml', 24 | ], 25 | # data files containing optionally loaded demonstration data 26 | 'demo': [ 27 | 'demo/demo_data.xml', 28 | ], 29 | } 30 | ``` 31 | 32 | 可用的声明字段有: 33 | 34 | `name` (`str`, 必填) 35 | 36 | 可阅读的模块名 37 | 38 | `version` (`str`) 39 | 40 | 该模块的版本,应遵循[语法版本号](https://semver.org/)规则 41 | 42 | `description` (`str`) 43 | 44 | 模块的扩展描述,格式为reStructuredText 45 | 46 | `author` (`str`) 47 | 48 | 模块作者的姓名 49 | 50 | `website` (`str`) 51 | 52 | 模块作者的网站URL 53 | 54 | `license` (`str`, 默认: `LGPL-3`) 55 | 56 | 模块的发行证书。可用的值有: 57 | 58 | * `GPL-2` 59 | * ``GPL-2 or any later version`` 60 | * GPL-3``GPL-3 or any later version`` 61 | * AGPL-3``LGPL-3`` 62 | * Other OSI approved licence 63 | * ``OEEL-1` (Odoo企业版证书 v1.0) 64 | * `OPL-1` (Odoo自有证书 v1.0) 65 | * `其它资产` 66 | 67 | ``category` (`str`, 默认: `Uncategorized`) 68 | 69 | Odoo中的分类,模块的大概业务领域。 70 | 71 | 虽然推荐使用 [已有分类](https://github.com/odoo/odoo/blob/13.0/odoo/addons/base/data/ir_module_category_data.xml),但字段时自由形式的并会补时创建未知的分类。作业帮行者无疆有可使用分隔符 Category hierarchies can be cr `/`进行创建,如 `Foo / Bar` 会创建一个分类`Foo`,并创建分类 `Bar` 为 `Foo`的子分类,且会将`Bar`设置为模块的分类。 72 | 73 | `depends` (`list(str)`) 74 | 75 | 必须在其之前加载的Odoo模块,要么因为该模板使用了它们创建的功能或因为其修改了它们定义的资源。在安装模块时,其所有依赖会在它之前安装。类似地依赖会在模块加载完之间加载。 76 | 77 | `data` (`list(str)`) 78 | 79 | 必须保持通过模块安装或更新的数据文件列表。来自模块根目录的路径列表 80 | 81 | `demo` (`list(str)`) 82 | 83 | 仅在*演示模式*下安装或更新的数据文件列表 84 | 85 | `auto_install` (`bool`, 默认: `False`) 86 | 87 | `若为True`,这个模块会自动在其所有依赖已安装时进行安装。 88 | 89 | 通常用于实现两个其它独立模块协同集成的“链接模块”。 90 | 91 | 例如 `sale_crm` 同时依赖于 `sale` 和 `crm` 并设置为 `auto_install`。在安装了`sale` 及 `crm` 的时候,它自动添加追踪订单的CRM活动,而`sale` 或 `crm` 并不知道彼此的存在 92 | 93 | `external_dependencies` (`dict(key=list(str))`) 94 | 95 | 包含python 和/或二进制依赖的字典。 96 | 97 | 对于python依赖,`python`键必须为这个字典定义并应分配一个导入的 python模块列表。 98 | 99 | 对于二进制依赖, `bin` 键必须为定义典定义且应分配一个二进制可执行名称的列表。 100 | 101 | 在未安装python模块时或主机或二进制没在主机的PATH环境变量中找到时不会安装该模块。 102 | 103 | `application` (`bool`, 默认: `False`) 104 | 105 | 模块是否应被看成是安整的应用 (`True`) 或仅是一个向已有应用模块提供功能支持的技术模块 (`False`) 。 106 | 107 | `css` (`list(str)`) 108 | 109 | 指定带有导入的自定义规则的css文件,这些文件应位于该模块的`static/src/css` 中。 110 | 111 | `images` (`list(str)`) 112 | 113 | 指定模块所使用的图片文件。 114 | 115 | `installable` (`bool` 默认: `True`) 116 | 117 | 用户是否能通过Web UI安装该模块。 118 | 119 | `maintainer` (`str`) 120 | 121 | 负责维护该模块的人或组织,默认假定作者就是维护人员。 122 | 123 | `{pre_init, post_init, uninstall}_hook` (`str`)模块安装/卸载的钩子,它们的值应为表示定义在模块`__init__.py`内的函数名的字符串。 124 | 125 | `pre_init_hook` 接收游标作为其唯一的参数,这个函数在模块安装之前执行。 126 | 127 | `post_init_hook` 接收一个游标及仓库作为其参数,该函数在模块安装之后执行。 128 | 129 | `uninstall_hook` 接收一个游标及仓库作为其参数,该函数在模块卸载之后执行。 130 | 131 | 这些钩子应仅在配置/清理时使用,要求使用这个模块的场景是通过 api 要么非常复杂要么无法办到时。 132 | 133 | -------------------------------------------------------------------------------- /tutorials/profiling-odoo-code.md: -------------------------------------------------------------------------------- 1 | # Odoo代码性能测试 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | ### ⚠️警告 6 | 7 | 本教程要求 [已安装Odoo](https://alanhou.org/odoo-13-installing-odoo/) 并 [编写Odoo代码](https://alanhou.org/odoo-13-building-module/) 8 | 9 | ## 方法的图形化 10 | 11 | Odoo内嵌有性能测试器。这一内嵌性能测试器的输出可用于生成由方法所触发调用、查询数、方法内部花费时间及方法及其调用的子方法所花费时间的图表。 12 | 13 | ``` 14 | from odoo.tools.misc import profile 15 | [...] 16 | @profile('/temp/prof.profile') 17 | def mymethod(...) 18 | ``` 19 | 20 | 这会生成一个名为/temp/prof.profile的文件 21 | 22 | 一个名为 *gprof2dot* 的工具会通过这一结果生成图表: 23 | 24 | ``` 25 | gprof2dot -f pstats -o /temp/prof.xdot /temp/prof.profile 26 | ``` 27 | 28 | 一个名为 *xdot* 的工具将显示所生成图表: 29 | 30 | ``` 31 | xdot /temp/prof.xdot 32 | ``` 33 | 34 | ## 方法日志 35 | 36 | 另一个性能优化器可用于记录方法的统计数据: 37 | 38 | ``` 39 | from odoo.tools.profiler import profile 40 | [...] 41 | @profile 42 | @api.model 43 | def mymethod(...): 44 | ``` 45 | 46 | 一旦待分析的方法完成重审后数据会显示为数据统计日志。 47 | 48 | ``` 49 | 2018-03-28 06:18:23,196 22878 INFO openerp odoo.tools.profiler: 50 | calls queries ms 51 | project.task ------------------------ /home/odoo/src/odoo/addons/project/models/project.py, 638 52 | 53 | 1 0 0.02 @profile 54 | @api.model 55 | def create(self, vals): 56 | # context: no_log, because subtype already handle this 57 | 1 0 0.01 context = dict(self.env.context, mail_create_nolog=True) 58 | 59 | # for default stage 60 | 1 0 0.01 if vals.get('project_id') and not context.get('default_project_id'): 61 | context['default_project_id'] = vals.get('project_id') 62 | # user_id change: update date_assign 63 | 1 0 0.01 if vals.get('user_id'): 64 | vals['date_assign'] = fields.Datetime.now() 65 | # Stage change: Update date_end if folded stage 66 | 1 0 0.0 if vals.get('stage_id'): 67 | vals.update(self.update_date_end(vals['stage_id'])) 68 | 1 108 631.8 task = super(Task, self.with_context(context)).create(vals) 69 | 1 0 0.01 return task 70 | 71 | Total: 72 | 1 108 631.85 73 | ``` 74 | 75 | ## Dump栈 76 | 77 | 向Odoo进程发送SIGQUIT信号(仅对POSIX可用)会让这个进程输出带有消息级别的当前栈跟踪进行日志。在 odoo进程看起来卡住时,向进程发送这个信号准许来知道进程在做什么,并让进程继续其任务。 78 | 79 | ## 追踪代码执行 80 | 81 | 向Odoo进程发送SIGQUIT信号通常足够了,但要查看进程在哪些地方比预期的性能要差的话,我们可以使用 pyflame 工具来替我们执行。 82 | 83 | ### 安装pyflame和flamegraph 84 | 85 | ``` 86 | # These instructions are given for Debian/Ubuntu distributions 87 | sudo apt install autoconf automake autotools-dev g++ pkg-config python-dev python3-dev libtool make 88 | git clone https://github.com/uber/pyflame.git 89 | git clone https://github.com/brendangregg/FlameGraph.git 90 | cd pyflame 91 | ./autogen.sh 92 | ./configure 93 | make 94 | sudo make install 95 | ``` 96 | 97 | ### 记录已执行代码 98 | 99 | 既然已经安装了pyflame,现在我们可以使用pyflame来记录已执行代码。这个工具会每秒多次记录进程的 stacktrace(栈追踪)。一旦完成,我们将通过执行图表来进行展示。 100 | 101 | ``` 102 | pyflame --exclude-idle -s 3600 -r 0.2 -p -o test.flame 103 | ``` 104 | 105 | 其中的 是想要图表化的odoo的进程ID。这会等待直至进程灭亡,最大值为1小时,并每秒获取5次追踪。通过pyflame的输出,我们可以使用flamegraph工具生成一张SVG 图表: 106 | 107 | ``` 108 | flamegraph.pl ./test.flame > ~/mycode.svg 109 | ``` 110 | 111 | ![img](https://www.odoo.com/documentation/13.0/_images/flamegraph.svg) -------------------------------------------------------------------------------- /reference/mobile-javascript.md: -------------------------------------------------------------------------------- 1 | # 移动端JavaScript 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | ## 导言 6 | 7 | 在Odoo 10.0中我们发布了移动端应用,可通过它访问所胡**Odoo app** (甚至是你自己的自定义模块)。 8 | 9 | 该应用是**Odoo Web** 和 **Native原生移动组件**的融合。换句话说这是在原生、移动、mobile容器中加载的Odoo Web实例。 10 | 11 | 本文讲解如何通过Odoo Web (借助JavaScript)访问移动原生组件如相机、振动、通知和Toast。为些,你不需要是一个移动开发者,如果了解Odoo JavaScript API就可以获取所有的移动端功能。 12 | 13 | ### ⚠️警告 14 | 15 | 这些功能仅在**Odoo 企业版10.0+** 中可使用 16 | 17 | ## 工作原理是什么? 18 | 19 | 移动端应用的内容工作原理如下: 20 | 21 | ![img](https://www.odoo.com/documentation/13.0/_images/mobile_working.jpg)当然,这是一个在移动原生Web容器中加载的网页。但集成的方式是你可以通过网页端JavaScript访问原生资源。 22 | 23 | WebPages (Odoo Web)在每层的上部,其中第二层是Odoo Web (JS)和原生移动组件之间的桥梁。 24 | 25 | 在触发任意来自JavaScript的调用时,它通过桥梁传递并且桥梁将其传递给原生调用者来执行该动作。 26 | 27 | 在原生组件完成其任务时,它再次传递给桥梁并且你可以获取到JavaScript中的输出。 28 | 29 | 原生组件处理花费的时间取决于从原生资源所请求的内容。如相机或GPS定位。 30 | 31 | ## 如何使用? 32 | 33 | 类似于Odoo Web框架,可通过从**web_mobile.rpc**获取对象来在任意地方使用移动端API 34 | 35 | ![img](https://www.odoo.com/documentation/13.0/_images/odoo_mobile_api.png)移动端RPC对象提供一个可用的方法列表 (仅配合移动端应用使用)。 36 | 37 | 查看方法是否可用,然后执行它。 38 | 39 | ### 方法 40 | 41 | 每个方法返回一个JQuery延时对象,它返回一个数据JSON字典 42 | 43 | #### 在设备中显示Toast 44 | 45 | ###### `showToast()` 46 | 47 | 参数 48 | 49 | - **args** (`object`) – 显示的**消息**文本 50 | 51 | toast提供有关小弹窗中操作的简单反馈。它仅填充消息所要求的空间且当前活动保持可见和交互性。 52 | 53 | ``` 54 | mobile.methods.showToast({'message': 'Message sent'}); 55 | ``` 56 | 57 | ![img](https://www.odoo.com/documentation/13.0/_images/toast.png) 58 | 59 | #### 振动设备 60 | 61 | ###### `vibrate()` 62 | 63 | 参数 64 | 65 | - **args** (`object`) – 在指定时间(按毫秒)内持续振动。 66 | 67 | 按照给定时长振动移动设备。 68 | 69 | ``` 70 | mobile.methods.vibrate({'duration': 100}); 71 | ``` 72 | 73 | #### 显示带有动作的snackbar 74 | 75 | ###### `showSnackBar()` 76 | 77 | 参数 78 | 79 | - **args** (`object`) – (*必传*) 在snackbar中显示的Snackbar及在Snackbar中的动作**按钮标签**(可选) 80 | 81 | 返回 82 | 83 | 若用户点击动作则为`True`,若在一段时间后SnackBar自动消失则为 `False` 。 84 | 85 | Snackbar对操作提供轻量的反馈。它们在移动端屏幕的底部或在更大设备的左下角显示简短消息。Snackbar位于屏幕上所有其它元素的之上且一次只能显示一个。 86 | 87 | ``` 88 | mobile.methods.showSnackBar({'message': 'Message is deleted', 'btn_text': 'Undo'}).then(function(result){ 89 | if(result){ 90 | // 执行 undo 操作 91 | }else{ 92 | // 取消Snack Bar 93 | } 94 | }); 95 | ``` 96 | 97 | ![img](https://www.odoo.com/documentation/13.0/_images/snackbar.png) 98 | 99 | #### 显示通知 100 | 101 | ###### `showNotification()` 102 | 103 | 参数 104 | 105 | - **args** (`object`) – 标准通知中通知的**标题**(第一行) ,通知的**信息**(第二行)。 106 | 107 | 通知是一个在应用的常规UI之外对用户显示的信息。 在告知系统发布通知时,它首先在通知区以一个图标形式出现。要查看通知的详情,用户打开通知列表。通知区和通知列表都是系统控制的区域,用户可在任意时刻查看。 108 | 109 | ``` 110 | mobile.showNotification({'title': 'Simple Notification', 'message': 'This is a test for a simple notification'}) 111 | ``` 112 | 113 | ![img](https://www.odoo.com/documentation/13.0/_images/mobile_notification.png) 114 | 115 | #### 在设备中创建联系人 116 | 117 | ###### `addContact()` 118 | 119 | 参数 120 | 121 | - **args** (`object`) – 带有联系人详情的字典。可能的键有 (姓名, 手机号, 电话, 传真, email, 网址, 街道, 街道2, 国家id, 州id, 城市, 邮编, parent_id, 函数和图像) 122 | 123 | 使用给定的联系人详情新建一个设备联系人。 124 | 125 | ``` 126 | var contact = { 127 | 'name': 'Michel Fletcher', 128 | 'mobile': '9999999999', 129 | 'phone': '7954856587', 130 | 'fax': '765898745', 131 | 'email': 'michel.fletcher@agrolait.example.com', 132 | 'website': 'http://www.agrolait.com', 133 | 'street': '69 rue de Namur', 134 | 'street2': false, 135 | 'country_id': [21, 'Belgium'], 136 | 'state_id': false, 137 | 'city': 'Wavre', 138 | 'zip': '1300', 139 | 'parent_id': [8, 'Agrolait'], 140 | 'function': 'Analyst', 141 | 'image': '<>' 142 | } 143 | 144 | mobile.methods.addContact(contact); 145 | ``` 146 | 147 | ![img](https://www.odoo.com/documentation/13.0/_images/mobile_contact_create.png) 148 | 149 | #### 扫描条形码 150 | 151 | ###### `scanBarcode()` 152 | 153 | 返回 154 | 155 | 通过任意条形码扫码`code` 156 | 157 | 条形码API实时在设备上监测任意方向的条形码。 158 | 159 | 条形码API可读取如下条形码格式: 160 | 161 | - 1维条形码: EAN-13, EAN-8, UPC-A, UPC-E, Code-39, Code-93, Code-128, ITF, Codabar 162 | - 2D条形码: 二维友, 数据矩阵, PDF-417, AZTEC 163 | 164 | ``` 165 | mobile.methods.scanBarcode().then(function(code){ 166 | if(code){ 167 | // 使用所扫描的编码执行操作 168 | } 169 | }); 170 | ``` 171 | 172 | #### 在设备中切换账户 173 | 174 | ###### `switchAccount()` 175 | 176 | 使用switchAccount在设备上从一个账户切换到另一个账户。 177 | 178 | ``` 179 | mobile.methods.switchAccount(); 180 | ``` 181 | 182 | ![img](https://www.odoo.com/documentation/13.0/_images/mobile_switch_account.png) -------------------------------------------------------------------------------- /reference/translating-modules.md: -------------------------------------------------------------------------------- 1 | # 模块翻译 2 | 3 | - 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | 这部分讲解如何对自己的模块进行翻译。 6 | 7 | 如果想对Odoo本身进行翻译的藏南,请参见 [Odoo维基页面](https://github.com/odoo/odoo/wiki/Translations)。 8 | 9 | ## 导出可翻译词汇 10 | 11 | 你的模块中的词汇数结果是“隐式可翻译”, 即使你没有对翻译进行具体的操作也可以导出模块的可翻译词汇并能查找可操作的内容。 12 | 13 | 翻译通过登录后台界面并访问Settings ‣ Translations ‣ Import / Export ‣ Export Translations来导出 14 | 15 | - 将语言保持为默认 (新语言/空模板) 16 | - 选择[PO File](https://en.wikipedia.org/wiki/Gettext#Translating)格式 17 | - 选择模块 18 | - 点击Export下载文件 19 | 20 | [![img](https://www.odoo.com/documentation/13.0/_images/po-export.png)](https://www.odoo.com/documentation/13.0/_images/po-export.png)这会给出一个名为`*yourmodule*.pot` 的文件,应移动到 `*yourmodule*/i18n/` 目录。该文件是一个*PO 模板*,仅列出可翻译字段及通过什么创建实际翻译 (PO 文件)。PO文件可使用[msginit](https://www.gnu.org/software/gettext/manual/gettext.html#Creating)进行创建,有一个类似[POEdit](https://poedit.net/) 专门的翻译工具或者只是将模板拷贝到名为`*language*.po`的新文件。翻译文件应放到`*yourmodule*/i18n/`中,紧邻`*yourmodule*.pot`,并将在安装相应语言时自动(通过Settings ‣ Translations ‣ Languages)由Odoo加载 21 | 22 | 在安装或更新模块时所有已加载语言的翻译也会进行安装或更新 23 | 24 | ## 隐式导出 25 | 26 | Odoo自动从“data”类型内容导出可翻译字符串: 27 | 28 | - 在非QWeb视图中,会导出所有文本节点及`string`, `help`, `sum`, `confirm` 和 `placeholder` 属性的内容 29 | 30 | - QWeb模板(服务端及客户端),导出除 `t-translation="off"`代码块内的所有文本节点, `title`, `alt`, `label` 和 `placeholder`属性的内容也会进行导出 31 | 32 | - 对于 33 | 34 | `Field` 35 | 36 | , 除非它们的模型通过 37 | 38 | ``` 39 | _translate = False 40 | ``` 41 | 42 | 进行标记: 43 | 44 | - 其 `string` 和 `help` 属性会进行导出 45 | - 如出现 `selection` 及列表(或元组),会导出 46 | - 如若其`translate` 属性设置为 `True`,它们的所有(跨越所有记录的)已存在值会导出 47 | 48 | - `_constraints` 和 `_sql_constraints` 的帮助/错误信息会导出 49 | 50 | ## 显式导出 51 | 52 | 在Python或Javascript代码中更“迫切”的场景中, Odoo不能自动导出词,因此它们必须进行显式的标记来导出。这通过在函数调用中封装字面量字符串来实现。 53 | 54 | 在Python中,封装的函数是`odoo._()`: 55 | 56 | ``` 57 | title = _("Bank Accounts") 58 | ``` 59 | 60 | 在JavaScript中,封装的函数通常是 `odoo.web._t()`: 61 | 62 | ``` 63 | title = _t("Bank Accounts"); 64 | ``` 65 | 66 | ### ⚠️警告 67 | 68 | 仅有字面量字符串可标记为导出,表达式或变量不行。对于字符串需格式化的场景,这意味着格式字符串而非格式化后的字符串必须进行标记 69 | 70 | `_` 和 `_t` 懒翻译版本为python中为 `odoo._lt()` ,在javascript中为 `odoo.web._lt()` 。翻译查找仅在渲染时查找并可用于声明全局变量类方法的可翻译属性。 71 | 72 | ### 变量 73 | 74 | **不要** 提取可能起作用但不会正确地翻译文本: 75 | 76 | ``` 77 | _("Scheduled meeting with %s" % invitee.name) 78 | ``` 79 | 80 | **要** 在翻译查找之外设置动态变量: 81 | 82 | ``` 83 | _("Scheduled meeting with %s") % invitee.name 84 | ``` 85 | 86 | ### 代码块 87 | 88 | **不要** 在一些代码块或多行中分隔翻译: 89 | 90 | ``` 91 | # 不妥,后缀空格,上下文外的代码块 92 | _("You have ") + len(invoices) + _(" invoices waiting") 93 | _t("You have ") + invoices.length + _t(" invoices waiting"); 94 | 95 | # 不妥, 多个碎片翻译 96 | _("Reference of the document that generated ") + \ 97 | _("this sales order request.") 98 | ``` 99 | 100 | **要** 保持在一个代码块中,将全文本给到翻译器: 101 | 102 | ``` 103 | # 妥, 允许修改在翻译中数量的位置 104 | _("You have %s invoices wainting") % len(invoices) 105 | _.str.sprintf(_t("You have %s invoices wainting"), invoices.length); 106 | 107 | # 妥, 全句可理解 108 | _("Reference of the document that generated " + \ 109 | "this sales order request.") 110 | ``` 111 | 112 | ### 复数 113 | 114 | **不要** 按英文的方式设置词汇的复数: 115 | 116 | ``` 117 | msg = _("You have %s invoice") % invoice_count 118 | if invoice_count > 1: 119 | msg += _("s") 120 | ``` 121 | 122 | **要** 记住各种语言有不同的复数形式: 123 | 124 | ``` 125 | if invoice_count > 1: 126 | msg = _("You have %s invoices") % invoice_count 127 | else: 128 | msg = _("You have %s invoice") % invoice_count 129 | ``` 130 | 131 | ### 读取vs运行时间 132 | 133 | **不要** 在服务启动时调用翻译查询: 134 | 135 | ``` 136 | ERROR_MESSAGE = { 137 | # 不妥, 没有用户语言时在服务端启动时运行 138 | 'access_error': _('Access Error'), 139 | 'missing_error': _('Missing Record'), 140 | } 141 | 142 | class Record(models.Model): 143 | 144 | def _raise_error(self, code): 145 | raise UserError(ERROR_MESSAGE[code]) 146 | ``` 147 | 148 | **不要** 在读取javascript文件时调用翻译查询: 149 | 150 | ``` 151 | # 不妥, js _t 运行的过早 152 | var core = require('web.core'); 153 | var _t = core._t; 154 | var map_title = { 155 | access_error: _t('Access Error'), 156 | missing_error: _t('Missing Record'), 157 | }; 158 | ``` 159 | 160 | **要** 使用懒翻译查找方法: 161 | 162 | ``` 163 | ERROR_MESSAGE = { 164 | 'access_error': _lt('Access Error'), 165 | 'missing_error': _lt('Missing Record'), 166 | } 167 | 168 | class Record(models.Model): 169 | 170 | def _raise_error(self, code): 171 | # 在错误渲染时执行翻译查找 172 | raise UserError(ERROR_MESSAGE[code]) 173 | ``` 174 | 175 | 或 **要** 动态运行可翻译内容: 176 | 177 | ``` 178 | # 妥,在运行时运行 179 | def _get_error_message(self): 180 | return { 181 | access_error: _('Access Error'), 182 | missing_error: _('Missing Record'), 183 | } 184 | ``` 185 | 186 | **要** 在读取JS文件时翻译查找完成,在使用时用 `_lt` 而非 `_t`来翻译启发式规则: 187 | 188 | ``` 189 | # 妥, js _lt 进行懒运行 190 | var core = require('web.core'); 191 | var _lt = core._lt; 192 | var map_title = { 193 | access_error: _lt('Access Error'), 194 | missing_error: _lt('Missing Record'), 195 | }; 196 | ``` -------------------------------------------------------------------------------- /reference/web-controllers.md: -------------------------------------------------------------------------------- 1 | # 网页控制器 2 | 3 | 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | ## 控制器 6 | 7 | 控制器需要提供扩展性,很像 [`Model`](https://alanhou.org/odoo-13-orm-api/#odoo.models.Model),但无法使用相同的机制作为预设条件 (带有已加载模块的数据库) 尚不可使用(如未创建或未选择数据库)。 8 | 9 | 因此控制器具有其自己的扩展机制,与模型的机制相分离: 10 | 11 | 控制器通过[继承](https://docs.python.org/3/tutorial/classes.html#tut-inheritance) `Controller`来进行创建。 路由通过由 [`route()`](https://alanhou.org/odoo-13-web-controllers/#odoo.http.route)装饰的方法定义: 12 | 13 | ``` 14 | class MyController(odoo.http.Controller): 15 | @route('/some_url', auth='public') 16 | def handler(self): 17 | return stuff() 18 | ``` 19 | 20 | 要*重载*控制器,[继承](https://docs.python.org/3/tutorial/classes.html#tut-inheritance)其类并重载相关方法,如果需要重新暴露它们: 21 | 22 | ``` 23 | class Extension(MyController): 24 | @route() 25 | def handler(self): 26 | do_before() 27 | return super(Extension, self).handler() 28 | ``` 29 | 30 | - 有必要使用 [`route()`](https://alanhou.org/odoo-13-web-controllers/#odoo.http.route) 进行装饰来保持方法(及路由)可见:如方法未进行装饰就重新定义,会变成“未发布” 31 | 32 | - 合并所有方法的装饰器,如重载方法的装饰器没有参数则会保留此前的所有参数,所提供的任意参数会覆盖此前所定义参数,例: 33 | 34 | ``` 35 | class Restrict(MyController): 36 | @route(auth='user') 37 | def handler(self): 38 | return super(Restrict, self).handler() 39 | ``` 40 | 41 | 会修改对用户公共认证的`/some_url` (要求登录) 42 | 43 | ## API 44 | 45 | 46 | 47 | ### 路由 48 | 49 | ###### `odoo.http.route(*route=None*, ***kw*)` 50 | 51 | 装饰器让所装饰的方法成为请求的处理器。该方法必须要是`Controller`子类的一部分。 52 | 53 | 参数 54 | 55 | - **route** – 字符串或数组。决定哪种http请求匹配所装饰方法的路由部分。可以是单个字符串或字符串数组。参见 werkzeug的路由文档了解路由表达式的格式( http://werkzeug.pocoo.org/docs/routing/ )。 56 | 57 | - **type** – 请求的类型,可为`'http'` 或 `'json'`. 58 | 59 | - auth 60 | 61 | – 认证方法的类型,可为以下类型: 62 | 63 | - `user`: 用户必须认证且当前请求将使用用户的权限进行执行。 64 | - `public`: 用户可认证也可不认证。如未认证,当前请求会使用共享Public用户进行执行。 65 | - `none`: 即使用没有数据库,方法也一直是活跃的。主要由框架和认证模块使用。它们的请求代码对访问数据库没有任何作用,也没有表明当前数据库或当前用户的配置。 66 | 67 | - **methods** – 一个这个路由所应用的http方法的序列。如未指定,允许使用所有方法。 68 | 69 | - **cors** – Access-Control-Allow-Origin cors 指令值。 70 | 71 | - **csrf** ([`bool`](https://docs.python.org/3/library/functions.html#bool)) – 是否应为路由启用CSRF保护。默认为 `True`。参见[CSRF保护](https://alanhou.org/odoo-13-web-controllers/#csrf)了解更多内容。 72 | 73 | ### CSRF保护 74 | 75 | 版本9.0中新增。 76 | 77 | Odoo实现基于令牌的[CSRF保护](https://en.wikipedia.org/wiki/CSRF)。 78 | 79 | CSRF保护默认启用并应用于[**RFC 7231**](https://tools.ietf.org/html/rfc7231.html)中所定义的*不安全* HTTP 方法 ( `GET`, `HEAD`, `TRACE` 和 `OPTIONS`之外的所有方法)。 80 | 81 | CSRF保护通过名为`csrf_token`值作为请求表单数据的一部分以检查请求来实现。 该值作为验证的一部分从表单中删除并在你自己的表单处理过程中不进行考虑。 82 | 83 | 在为不安全方法(大多为表单等的POST)新增控制器时: 84 | 85 | - 如果表单在Python中生成,csrf令牌借由`request.csrf_token() {"jsonrpc": "2.0", 230 | "method": "call", 231 | "params": {"context": {}, 232 | "arg1": "val1" }, 233 | "id": null} 234 | 235 | <-- {"jsonrpc": "2.0", 236 | "result": { "res1": "val1" }, 237 | "id": null} 238 | ``` 239 | 240 | 产生错误的请求: 241 | 242 | ``` 243 | --> {"jsonrpc": "2.0", 244 | "method": "call", 245 | "params": {"context": {}, 246 | "arg1": "val1" }, 247 | "id": null} 248 | 249 | <-- {"jsonrpc": "2.0", 250 | "error": {"code": 1, 251 | "message": "End user error message.", 252 | "data": {"code": "codestring", 253 | "debug": "traceback" } }, 254 | "id": null} 255 | ``` 256 | 257 | ### 响应 258 | 259 | ###### `*class* odoo.http.Response(**args*, ***kw*)` 260 | 261 | 通过控制器路由链传递的Response对象。 262 | 263 | [`werkzeug.wrappers.Response`](https://werkzeug.palletsprojects.com/en/0.16.x/wrappers/#werkzeug.wrappers.Response) 参数之外,这个类的构造方法可针对QWeb懒渲染接收如下的额外参数。 264 | 265 | 参数 266 | 267 | - **template** (`basestring`) – 等渲染的模板 268 | - **qcontext** ([`dict`](https://docs.python.org/3/library/stdtypes.html#dict)) – 要使用的渲染上下文 269 | - **uid** ([`int`](https://docs.python.org/3/library/functions.html#int)) – 针对ir.ui.view渲染调用所使用的用户 id,`None` 时使用请求的用户 (默认) 270 | 271 | 这些属性在Response对象中作为参数使用且可在渲染之前的任意时刻进行更改 272 | 273 | 还暴露[`werkzeug.wrappers.Response`](https://werkzeug.palletsprojects.com/en/0.16.x/wrappers/#werkzeug.wrappers.Response)的所有属性和方法。 274 | 275 | ###### `render()` 276 | 277 | 渲染Response的模板,返回结果 278 | 279 | ###### `flatten()` 280 | 281 | 强制渲染响应模板,设置结果为响应体并清除`template` -------------------------------------------------------------------------------- /reference/qweb-reports.md: -------------------------------------------------------------------------------- 1 | # QWeb报表 2 | 3 | - 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | - 以HTML/QWeb像在Odoo中其它普通视图那样编写报表。 你可以使用通常的[QWeb控制流工作](#reference-qweb) 。PDF渲染本身由 [wkhtmltopdf](https://wkhtmltopdf.org/)执行。如果你想要对某个模型创建报表,会需要定义这个[报表](#reference-reports-report)及其需要使用的[报表模板](#reference-reports-templates)。 如果你想要,也可以为报表指定一个特定的[纸张格式](#reference-reports-paper-formats)。最终,如果需要访问自己的模型之外的内容,可以定义一个给予你访问更多模型及模板中记录的权限的[自定义报表](#reference-reports-custom-reports)类。 5 | 6 | ## 报表 7 | 8 | 每个报表必须由 [报表动作](https://alanhou.org/odoo-13-actions/#reference-actions-report)声明。 9 | 10 | 为进行简化,``元素快捷方式在定义报表可以使用, 而非需要手动设置 [动作](https://alanhou.org/odoo-13-actions/#reference-actions-report)及其周边内容。这个 `` 可以接收如下属性: 11 | 12 | - `id` 13 | 14 | 所生成记录的[外部id](https://www.odoo.com/documentation/13.0/glossary.html#term-external-id) 15 | 16 | - `name` (必填) 17 | 18 | 仅在某种列表中查找内容时用于报表的助记内容/描述 19 | 20 | - `model` (必填) 21 | 22 | 你的报表会相关的模型 23 | 24 | - `report_type` (必填) 25 | 26 | PDF报表的`qweb-pdf` 或HTML的 `qweb-html` 27 | 28 | - `report_name` 29 | 30 | 你的报表名称(将会是PDF的输出名) 31 | 32 | - `groups` 33 | 34 | 允许浏览/使用当前报表的组的[`Many2many`](https://alanhou.org/odoo-13-orm-api/#odoo.fields.Many2many) 字段 35 | 36 | - `attachment_use` 37 | 38 | 若设置为True, 使用 `attachment`表达式所生成的名称存储为附件的报表;如果需要仅生成一次报表可以使用它 (例如出于法律原因) 39 | 40 | - `attachment` 41 | 42 | 定义报表名称的python 表达式;记录可作为 `object`变量访问 43 | 44 | - `paperformat` 45 | 46 | 希望使用的纸张格式的外部id(如未指定默认为公司的纸张格式) 47 | 48 | 例: 49 | 50 | ``` 51 | 62 | ``` 63 | 64 | 65 | 66 | ## 报表模板 67 | 68 | ### 最小化可选模板 69 | 70 | 最小化模板像下面这样: 71 | 72 | ``` 73 | 85 | ``` 86 | 87 | 调用`external_layout` 会在报表上添加头部和底部。PDF内容体是 `
`内部的内容。 模板的 `id` 必须为在报表声明中指定的名称;例如对上面的报表为 `account.report_invoice` 。因为这是一个QWeb模板,你可以访问由模板接收的`docs`对象的所有字段。 88 | 89 | 有一些可在报表中访问的具体变量,主要有: 90 | 91 | - `docs` 92 | 93 | 针对当前报表的记录 94 | 95 | - `doc_ids` 96 | 97 | 针对 `docs`记录的id列表 98 | 99 | - `doc_model` 100 | 101 | 针对`docs` 记录的模型 102 | 103 | - `time` 104 | 105 | 对Python标准库 [`time`](https://docs.python.org/3/library/time.html#module-time)的引用 106 | 107 | - `user` 108 | 109 | 打印报表的用户的`res.user` 记录 110 | 111 | - `res_company` 112 | 113 | 当前 `user`的公司的记录 114 | 115 | 如果你希望访问模板中的记录/模型的其它记录,会需要用到[自定义报表](#reference-reports-custom-reports)。 116 | 117 | ### 可翻译模板 118 | 119 | 如果要翻译报表 (如翻译到伙伴的语言),需要定义两个模板: 120 | 121 | - 主报表模板 122 | - 可翻译的文档 123 | 124 | 然后可以调用通过将属性设置 `t-lang` 为语言代码(例如`fr` 或 `en_US`)或是记录字段的主模板中的可翻译文档。如果使用可翻译的字段(如国家名、销售条件等)还需要通过相应的上下文重新浏览相关记录。 125 | 126 | ### ⚠️警告 127 | 128 | 如果报表模板不使用可翻译记录字段,不需要在另一种语言中重新浏览记录且这样会影响性能。 129 | 130 | 例如,我们来看一下Sale模块中的销售订单报表: 131 | 132 | ``` 133 | 134 | 141 | 142 | 143 | 159 | ``` 160 | 161 | 主模板调用可翻译模板,将 `doc.partner_id.lang` 作为 `t-lang` 参数,因此它会以伙伴的语言进行渲染。这样,每个订单会以对应客户的语言进行打印。如果希望仅翻译文档内容体,但保留头部和底部为默认语言,需要像下面这样调用报表的外部布局: 162 | 163 | ``` 164 | 165 | ``` 166 | 167 | 注意这样仅在调用外部模板时起作用, 不能通过对`t-call`以外的xml节点设置 `t-lang`属性来翻译文档的部分内容。如果要翻译模板的部分内容,可以使用这一部分模板来创建外部模板并通过带`t-lang`属性的主模板调用它。 168 | 169 | ### 条形码 170 | 171 | 条形码为由控制器返回的图像,可轻易地借助QWeb语法来在报表中内嵌(例如参见[属性](#reference-qweb-attributes)): 172 | 173 | ``` 174 | 175 | ``` 176 | 177 | 可以查询字符串传递更多的参数: 178 | 179 | ``` 180 | 182 | ``` 183 | 184 | ### 实用备注 185 | 186 | - 可在报表中使用Twitter Bootstrap和FontAwesome类 187 | 188 | - 可在模板中直接放置本地CSS 189 | 190 | - 可通过继承模板来在主报表中插入全局CSS并插入你自己的CSS: 191 | 192 | ``` 193 | 202 | ``` 203 | 204 | - 如果在 PDF报表中缺失了样式,请查看[这些指南](https://alanhou.org/odoo-13-building-module/#reference-backend-reporting-printed-reports-pdf-without-styles)。 205 | 206 | 207 | 208 | ## 纸张格式 209 | 210 | 纸张格式是`report.paperformat` 记录并可包含如下属性: 211 | 212 | - `name` (必传) 213 | 214 | 仅用于在某种列表中查看报表的助记内容/描述 215 | 216 | - `description` 217 | 218 | 格式的简短描述 219 | 220 | - `format` 221 | 222 | 是预定义格式(A0到A9, B0到 B10, 法律文书, 信件, 公报,…) 或 `自定义`;默认为 A4。你果定义页面大小时不能使用非自定义格式。 223 | 224 | - `dpi` 225 | 226 | 输出DPI;默认为90 227 | 228 | - `margin_top`, `margin_bottom`, `margin_left`, `margin_right` 229 | 230 | 单位为mm的边框大小 231 | 232 | - `page_height`, `page_width` 233 | 234 | 单位为mm的页面大小 235 | 236 | - `orientation` 237 | 238 | 横向或纵向 239 | 240 | - `header_line` 241 | 242 | 显示头部线的布尔值 243 | 244 | - `header_spacing` 245 | 246 | 单位为mm的头部间距 247 | 248 | 例: 249 | 250 | ``` 251 | 252 | French Bank Check 253 | 254 | custom 255 | 80 256 | 175 257 | Portrait 258 | 3 259 | 3 260 | 3 261 | 3 262 | 263 | 3 264 | 80 265 | 266 | ``` 267 | 268 | 269 | 270 | ## 自定义报表 271 | 272 | 报表模型有默认的`get_html`函数,会查找名为`report.*module.report_name*`的模型。如若存在,会使用它来调用QWeb引擎;否则会使用一个通用函数。如果希望通过在模板中包含更多内容来自定义报表 (例如像其它模型中记录),可以定义这个模型,重写函数 `_get_report_values` 并在 `docargs` 字典中传递对象: 273 | 274 | ``` 275 | from odoo import api, models 276 | 277 | class ParticularReport(models.AbstractModel): 278 | _name = 'report.module.report_name' 279 | 280 | @api.model 281 | def _get_report_values(self, docids, data=None): 282 | report_obj = self.env['ir.actions.report'] 283 | report = report_obj._get_report_from_name('module.report_name') 284 | docargs = { 285 | 'doc_ids': docids, 286 | 'doc_model': report.model, 287 | 'docs': self, 288 | } 289 | return docargs 290 | ``` 291 | 292 | 293 | 294 | ## 自定义字体 295 | 296 | If you want to use如果希望使用自定义字段则需要向`web.reports_assets_common`资源包添加自定义字体相相关联的 less/CSS。向`web.assets_common` 或 `web.assets_backend`添加自定义字体不会让该字体在QWeb可用。 297 | 298 | 例: 299 | 300 | ``` 301 | 306 | ``` 307 | 308 | 即使在(除`web.reports_assets_common`以外的)其它资源包中使用过,也需要在这个less文件中定义 `@font-face`。 309 | 310 | 例: 311 | 312 | ``` 313 | @font-face { 314 | font-family: 'MonixBold'; 315 | src: local('MonixBold'), local('MonixBold'), url(/your_module/static/src/fonts/MonixBold-Regular.otf) format('opentype'); 316 | } 317 | 318 | .h1-title-big { 319 | font-family: MonixBold; 320 | font-size: 60px; 321 | color: #3399cc; 322 | } 323 | ``` 324 | 325 | 在将这一 less添加到资源包中以后就可以在自定义QWeb报表中使用该类了- 配合中为 `h1-title-big`。 326 | 327 | ## 报表是网页 328 | 329 | 报表通过report模块动态生成并可直接通过URL进行访问: 330 | 331 | 例如,可以通过http:///report/html/sale.report_saleorder/38来以html模式访问销售订单报表 332 | 333 | 或者通过http:///report/pdf/sale.report_saleorder/38访问pdf版本 -------------------------------------------------------------------------------- /reference/actions.md: -------------------------------------------------------------------------------- 1 | # 动作 2 | 3 | - 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | 动作定义对应用户动作的系统行为:登录、动作按钮、发票选取 … 动作可存储在数据库中或直接返回如按钮方法的字典。所有的动作有两个必选属性: 6 | 7 | - `type` 8 | 9 | 当前动作的分类,定义可使用哪些字段以及如何解析动作 10 | 11 | - `name` 12 | 13 | 针对动作的用户可读的简短描述,可在客户端界面中显示 14 | 15 | - `binding_model_id` 16 | 17 | 若进行设置,在给定模型的动作栏中的可用动作对于服务端动作,使用 `model_id`。 18 | 19 | 客户端可以获取4种形式的动作: 20 | 21 | - - `False` 22 | 23 | 若当前有动作对话框处于打开状态,进行关闭 24 | 25 | - - 字符串 26 | 27 | 若匹配 [客户端动作](#reference-actions-client),解析为客户端动作标签,否则视为数字 28 | 29 | - - 数字 30 | 31 | 读取数据库中的相应动作记录,可为数据库标识符或 [外部id](https://www.odoo.com/documentation/13.0/glossary.html#term-external-id) 32 | 33 | - - 字典 34 | 35 | 视为客户端描述符并执行 36 | 37 | ## 绑定 38 | 39 | 除两个必选属性外,所有的动作还可以有用于在任意模型的上下文菜单中展示动作的*可选*属性: 40 | 41 | - `binding_model_id` 42 | 43 | 指定动作所绑定的模型 44 | 45 | - `binding_type` 46 | 47 | 指定所绑定的类型,大多为动作出现在哪个上下文菜单之下`action` (默认)指定动作会出现在绑定模型Action上下文菜单中。`report`指定动作会出现在所绑定模型的Print上下文菜单中 48 | 49 | - `binding_view_types` 50 | 51 | 视图的逗号分隔列表,其中动作出现在上下文菜单中,大部分“列表”及/或“表单”。默认为`list,form` (列表及表单) 52 | 53 | 54 | 55 | ## 窗口动作(`ir.actions.act_window`) 56 | 57 | 大部分常用动作类型,用于展示通过[视图](https://alanhou.org/odoo-13-views/#reference-views)的模型可视化:定义一组视图类型的模型(可能为模型的指定记录)窗口动作 (及可能的指定视图) f 58 | 59 | 其字段有: 60 | 61 | - `res_model` 62 | 63 | 用于展示视图的模型 64 | 65 | - `views` 66 | 67 | `(view_id, view_type)` 对的列表。每组的第二个元素是视图的分类 (tree, form, graph, …) ,第一个是可选的数据库 id (或 `False`)。若未提供 id,客户端应获取对所请求模型指定类型的默认视图(默认通过[`fields_view_get()`](https://alanhou.org/odoo-13-orm-api/#odoo.models.Model.fields_view_get)来实现). 列表的第一个类型是默认视图类型列表,在动作执行时会默认打开。每个视图类型在列表中最多出现一次。 68 | 69 | - `res_id` (可选) 70 | 71 | 若默认视图为 `form`,指定要加载的记录(否则应创建一条新记录) 72 | 73 | - `search_view_id` (可选) 74 | 75 | `(id, name)` 对, `id` 为针对动作所加载的指定搜索视图的数据库标识符。默认获取模型的默认搜索视图 76 | 77 | - `target` (可选) 78 | 79 | 是否应在主内容区 (`current`)中以全屏模式(`fullscreen`)或对话框/弹窗(`new`)中打开视图。使用 `main` 代替 `current` 来清除面包屑导航。默认为`current`。 80 | 81 | - `context` (可选) 82 | 83 | 传递给视图的额外上下文数据 84 | 85 | - `domain` (可选) 86 | 87 | 隐式添加给所有视图搜索查询的过滤作用域 88 | 89 | - `limit` (可选) 90 | 91 | 默认在列表中显示的记录数。在网页客户端中默认为80 92 | 93 | 例如,要通过列表及表单视图打开客户 (配合 `customer` 标记集) : 94 | 95 | ``` 96 | { 97 | "type": "ir.actions.act_window", 98 | "res_model": "res.partner", 99 | "views": [[False, "tree"], [False, "form"]], 100 | "domain": [["customer", "=", true]], 101 | } 102 | ``` 103 | 104 | 或在新对话框中打开指定产品(单独获取)的表单视图: 105 | 106 | ``` 107 | { 108 | "type": "ir.actions.act_window", 109 | "res_model": "product.product", 110 | "views": [[False, "form"]], 111 | "res_id": a_product_id, 112 | "target": "new", 113 | } 114 | ``` 115 | 116 | 数据库中的窗口动作有一些应由客户端忽略的不同字段,大多数用于组成`views` 列表: 117 | 118 | - `view_mode` (默认= `tree,form` ) 119 | 120 | 视图类型的逗号分隔列表作为字符串(/!\ 无空格 /!\)。所有这些类型会在生成的`views` 列表中出现 (至少有一个`False` view_id) 121 | 122 | - `view_ids` 123 | 124 | M2M[1](#notquitem2m) 的视图对象,定义 `views`的初始内容Act_window视图也可通过`ir.actions.act_window.view`清晰地定义。如果你打算允许模型的多个视图,推荐使用ir.actions.act_window.view 而不是动作 `view_ids`` tree ` 125 | 126 | - `view_id` 127 | 128 | 在类型是`view_mode`列表的一部分且没有由`view_ids`中的视图进行填充时,添加到 `views` 中的指定视图 129 | 130 | These are mostly used when defining actions from这些大多在 [数据文件](https://www.odoo.com/documentation/13.0/reference/data.html#reference-data)中定义动作时使用: 131 | 132 | ``` 133 | 134 | A Test Action 135 | some.model 136 | graph 137 | 138 | 139 | ``` 140 | 141 | 即使不是模型的默认视图,也将使用“my_specific_view”视图。 142 | 143 | 服务端的 `views` 序列的组合如下: 144 | 145 | - 通过 `view_ids` 获取每个`(id, type)`(通过`sequence`排序) 146 | - 若定义了 `view_id` 且未填充其类型,追加其 `(id, type)` 147 | - 对每个 `view_mode`中未填充的类型,追加 `(False, type)` 148 | 149 | [[1\]](#id1) 技术上不是 M2M: 添加序列字段及可能只由视图类型组成,不带有视图id。 150 | 151 | 152 | 153 | ## URL动作 (`ir.actions.act_url`) 154 | 155 | (website/web page) via an 允许Odoo动作打开URL(网站/网页)。可由两个字段进行自定义: 156 | 157 | - `url` 158 | 159 | 在激活动作时打开的地址 160 | 161 | - `target` 162 | 163 | 若为 `new`在新窗口/页面打开该地址,若为 `self`使用该页面替换当前内容。默认值为 `new` 164 | 165 | ``` 166 | { 167 | "type": "ir.actions.act_url", 168 | "url": "https://odoo.com", 169 | "target": "self", 170 | } 171 | ``` 172 | 173 | 将使用Odoo首页替换当前内容版块。 174 | 175 | 176 | 177 | ## 服务端动作 (`ir.actions.server`) 178 | 179 | ###### `*class* odoo.addons.base.models.ir_actions.IrActionsServer(*pool*, *cr*)` 180 | 181 | 服务端动作模型。服务端动作在基模型上运作并且提供种类可自动执行的动作类型,例如,手动通过在 More 上下文菜单中添加动作来使用基动作规则。 182 | 183 | 从Odoo 8.0开始,在动作表单视图中出现了‘Create Menu Action’按钮。它在基模型的More菜单中创建一个入口。这允许在界面中创建服务端动作并以批量模式进行运行。 184 | 185 | 可以使用的动作有: 186 | 187 | - ‘Execute Python Code’: 将会执行的 Python 代码块 188 | - ‘Create a new Record’: 使用新值新建记录 189 | - ‘Write on a Record’: 更新记录值 190 | - ‘Execute several actions’: 定义触发一些其它服务端动作的动作 191 | 192 | 允许通过任意有效动作位置触发复杂服务端代码。仅有两个字段与客户端相关: 193 | 194 | - `id` 195 | 196 | 待运行服务端动作的数据库中的标识符 197 | 198 | - `context` (可选) 199 | 200 | 在运行服务端动作时使用的上下文数据 201 | 202 | In-database records 数据库中的记录很明显的更丰富并可执行一些基于它们的`state`的特定或通用动作。一些字段 (及相应行为) 在状态之间进行分享: 203 | 204 | - `model_id` 205 | 206 | 链接到动作的Odoo模型。 207 | 208 | ``` 209 | state 210 | ``` 211 | 212 | - `code`: 执行通过`code` 参数给定的python代码。 213 | - `object_create`: 根据`fields_lines` 规格新建`crud_model_id`模型的记录。 214 | - `object_write`: 按照`fields_lines` 规格更新当前记录。 215 | - `multi`: 执行通过`child_ids` 参数给定的一些动作。 216 | 217 | ### 状态字段 218 | 219 | 根据其状态通过不同的字段来定义行为。相关的状态在每个字段后给出。 220 | 221 | - `code` (代码) 222 | 223 | 指定调用动作时所要执行的Python代码块` Res Partner Server Action raise Warning(record.name) `代码块中可定义`action`的变量,它将以要执行的下一个动作返回客户端:` Res Partner Server Action if record.some_condition(): action = { "type": "ir.actions.act_window", "view_mode": "form", "res_model": record._name, "res_id": record.id, } `会要求客户端在满足某些条件时打开记录的表单 224 | 225 | - `crud_model_id` (创建)(必传) 226 | 227 | 新建记录的所在模型 228 | 229 | - `link_field_id` (创建) 230 | 231 | `ir.model.fields`的many2one关联,指定当前记录的m2o字段,在其中应设置新创建字段(模型应匹配) 232 | 233 | - `fields_lines` (创建/写入) 234 | 235 | 在创建或拷贝记录时重载的字段。与字段的关联为 [`One2many`](https://alanhou.org/odoo-13-orm-api/#odoo.fields.One2many):`col1`在相关模型中设置`ir.model.fields` (`crud_model_id` 用于创建, `model_id` 用于更新)`value`字段的值,通过 `type`解析`type` (value|reference|equation)若为 `value`, `value` 字段解析为字面量值(可能会进行格式转换),若为`equation`,`value` 字段解析为Python 表达式并进行运行 236 | 237 | - `child_ids` (multi) 238 | 239 | 指定多个子动作 (`ir.actions.server`) 来启用多状态。如子动作本身返回动作,上一个会作为multi自己的下一个动作返回客户端 240 | 241 | 242 | 243 | ### 运行上下文 244 | 245 | 在服务端动作的运行上下文或周边存在很多键可以使用: 246 | 247 | - `model` 通过 `model_id`关联动作的模型对象 248 | - `record`/`records` 动作所触发的记录/记录集,可以为空。 249 | - `env` Odoo环境 250 | - `datetime`, `dateutil`, `time`, `timezone` 相应Python模块 251 | - `log: log(message, level='info')` 在ir.logging表中用于记录信息的日志函数 252 | - `Warning` 针对`Warning` 异常的构造器 253 | 254 | 255 | 256 | ## 报表动作(`ir.actions.report`) 257 | 258 | 触发报表打印 259 | 260 | - `name` (必传) 261 | 262 | 仅在查询一些排序列表中的某一个时用于报表的助记符/描述 263 | 264 | - `model` (必传) 265 | 266 | 报表相关的模型 267 | 268 | - `report_type` (default=qweb-pdf) 269 | 270 | 要么是用于PDF报表的 `qweb-pdf` ,要么是用于HTML报表的 `qweb-html` 271 | 272 | - `report_name` (必传) 273 | 274 | 报表的名称 (将会与PDF的输出名称相同) 275 | 276 | - `groups_id` 277 | 278 | 允许查看/使用当前报表用户组的[`Many2many`](https://alanhou.org/odoo-13-orm-api/#odoo.fields.Many2many) 字段 279 | 280 | - `multi` 281 | 282 | 若设置为`True`, 该动作将不会在表单视图中显示。 283 | 284 | - `paperformat_id` 285 | 286 | 希望用于此报表的对应于纸张格式的[`Many2one`](https://alanhou.org/odoo-13-orm-api/#odoo.fields.Many2one)字段(若未指定,会使用公司格式) 287 | 288 | - `attachment_use` 289 | 290 | 若设置为`True`, 该报表仅在请求的初次进行生成,随后会从存储的报表中重新打印,而不会每次都重新生成。可用于必须仅生成一次的报表 (例如出于法律原因) 291 | 292 | - `attachment` 293 | 294 | 定义报表名称的python表达式;记录可以 `object`变量进行访问 295 | 296 | 297 | 298 | ## 客户端动作(`ir.actions.client`) 299 | 300 | 触发完全在客户端实现的动作。 301 | 302 | - `tag` 303 | 304 | 动作的客户端标识符, 客户端应知道如何响应的任意字符串 305 | 306 | - `params` (可选) 307 | 308 | 与客户端动作标记一起发送到客户端的附加数据的Python字典 309 | 310 | - `target` (可选) 311 | 312 | 客户端动作是否应在主内容区(`current`)、以全屏模式(`fullscreen`)或对话框/弹窗(`new`)中打开。使用 `main` 代替`current` 来清除面包屑。默认值为 `current`。 313 | 314 | ``` 315 | { 316 | "type": "ir.actions.client", 317 | "tag": "pos.ui" 318 | } 319 | ``` 320 | 321 | 告诉客户端启动POS 界面,服务端并不了解 POS 界面的运行方式。 322 | 323 | 324 | 325 | ## 自动化动作(`ir.cron`) 326 | 327 | 以预定义频率自动触发的动作。 328 | 329 | - `name` 330 | 331 | 自动化动作的名称 (主要在日志显示中使用) 332 | 333 | - `interval_number` 334 | 335 | 在两个动作执行之间的*nterval_type* 计量单位数 336 | 337 | - `interval_type` 338 | 339 | 频率间隔的计量单位(`minutes`, `hours`, `days`, `weeks`, `months`, 340 | 341 | - `numbercall` 342 | 343 | 这一动作需要运行的次数。如果动作要进行无限动作,设置为 `-1`。 344 | 345 | - `doall` 346 | 347 | 在服务重启时指定是否执行未执行动作的布尔值。 348 | 349 | - `model_id` 350 | 351 | 这一动作将会被调用的模型 352 | 353 | - `code` 354 | 355 | 动作的代码内容。可以是对模型方法的简单调用:`model.()` 356 | 357 | - `nextcall` 358 | 359 | 该动作的下一次计划执行日期(date/time 格式) 360 | 361 | -------------------------------------------------------------------------------- /reference/command-line-interface-odoo-bin.md: -------------------------------------------------------------------------------- 1 | # 命令行接口:odoo-bin 2 | 3 | - 本文来自[Odoo 13官方文档之开发者文档](../README.md)系列文章 4 | 5 | ## 运行服务 6 | 7 | ###### `-d , --database ` 8 | 9 | 在安装或更新文件时使用的数据库。提供一个逗号分隔列表,列表中提供数据库限制权限。 10 | 11 | 高级数据库选项请参见 [下方内容](#reference-cmdline-server-database)。 12 | 13 | ###### `-i , --init ` 14 | 15 | 在运行服务前要安装的模块的逗号分隔列表(要求有 [`-d`](#cmdoption-odoo-bin-d)选项)。 16 | 17 | ###### `-u , --update ` 18 | 19 | 在运行服务前要更新的模块的逗号分隔列表(要求有 [`-d`](#cmdoption-odoo-bin-d)选项)。 20 | 21 | ###### `--addons-path ` 22 | 23 | 模块所存储的目录的逗号分隔列表。这些目录供模块扫描。 24 | 25 | ###### `-c , --config ` 26 | 27 | 指供一个替代 [配置文件](#reference-cmdline-config) 28 | 29 | ###### `-s, --save` 30 | 31 | 保存服务端配置到当前配置文件中 (默认为`*$HOME*/.odoorc` ,可通过使用 [`-c`](#cmdoption-odoo-bin-c)进行重载)。 32 | 33 | ###### `--without-demo` 34 | 35 | 在模块安装时禁止加载演示数据的逗号分隔列表,使用 `all` 来针对所有模块。 36 | 37 | ###### `--test-enable` 38 | 39 | 在安装模块之后运行测试 40 | 41 | ###### `--test-tags 'tag_1,tag_2,...,-tag_n'` 42 | 43 | 选择通过使用标签运行的测试。 44 | 45 | ###### `--screenshots` 46 | 47 | 指定在HttpCase.browser_js测试失败时写入截屏快照的路径。 默认值为`/tmp/odoo_tests/*db_name*/screenshots` 48 | 49 | ###### `--screencasts` 50 | 51 | 启用录屏并指定写入录屏文件的路径。需要安装 `ffmpeg`工具来将各帧编码入视频文件中。否则将保存帧而不是视频文件。 52 | 53 | `1`, `t` 或 `true` 可用于使用同一目录作为上述的 `--screenshots` 选项。 54 | 55 | 56 | 57 | ### 数据库 58 | 59 | ###### `-r , --db_user ` 60 | 61 | 数据库用户名,用于连接PostgreSQL. 62 | 63 | ###### `-w , --db_password ` 64 | 65 | 若使用了 [密码验证](https://www.postgresql.org/docs/9.3/static/auth-methods.html#AUTH-PASSWORD)时,为数据库密码。 66 | 67 | ###### `--db_host ` 68 | 69 | 数据库服务端的主机 70 | 71 | - Windows上的`localhost` 72 | - 否则为UNIX套接字 73 | 74 | ###### `--db_port ` 75 | 76 | 数据库监听的端口,默认为5432 77 | 78 | ###### `--db-filter ` 79 | 80 | 隐藏不匹配``的数据库。过滤器是一个[正则表达式](https://docs.python.org/3/library/re.html),额外之处有: 81 | 82 | - `%h` 由所进行请求的完整主机名替换。 83 | - `%d`由所进行请求的子域名进行替换,`www` 除外(因此域名`odoo.com` 和 `www.odoo.com` 同时匹配数据库`odoo`)。这些运算是区分大小写的。添加选项 `(?i)` 来匹配所有数据库(因此域名 `odoo.com` 使用 `(?i)%d` 匹配数据库 `Odoo`). 84 | 85 | 自版本11开始,还可以通过使用–database参数并指定一个逗号分隔的数据库列表来限定对指定数据库的访问 86 | 87 | 在合并这两个参数时,db-filter替代限定数据库列表的逗号分隔列表,而逗号分隔列表用于执行像升级模块这类请求运算。 88 | 89 | ``` 90 | $ odoo-bin --db-filter ^11.*$ 91 | ``` 92 | 93 | 限制对名称以11开头的数据库的访问 94 | 95 | ``` 96 | $ odoo-bin --database 11firstdatabase,11seconddatabase 97 | ``` 98 | 99 | 限定仅访问两个数据库, 11firstdatabase 和 11seconddatabase 100 | 101 | ``` 102 | $ odoo-bin --database 11firstdatabase,11seconddatabase -u base 103 | ``` 104 | 105 | 限定仅访问两个数据库,11firstdatabase 和 11seconddatabase,并升级一个数据库中的 base模块:11firstdatabase。如果数据库11seconddatabase 不存在,会创建数据库并安装base模块 106 | 107 | ``` 108 | $ odoo-bin --db-filter ^11.*$ --database 11firstdatabase,11seconddatabase -u base 109 | ``` 110 | 111 | 限定对名称以11开头的数据库的访问,并对一个数据库的 base模块进行升级:11firstdatabase。如数据库11seconddatabase 不存在,会创建该数据库并安装 base 模块 112 | 113 | ###### `--db-template