关于odoo:Odoo-14-如何修改登录后首页

探讨是用户登录后看到的第一个页面。在大多数状况下,没有人心愿将探讨视为登录页面。但有许多应用程序依赖于探讨,因而您无奈卸载它。 Odoo 登录后默认关上主菜单中的第一项页面。所以更改登录页面的解决方案是将其设为第一项,这是由菜单项的 Sequence 字段决定。 更改菜单项地位激活开发者模式 – 在设置页面中能够找到.拜访设置 > 技术 > 用户界面 > 菜单项单击您想要将其设为登录页面的页面批改序列 - 数字越小,它在菜单上呈现的地位就越靠前。将页面的 Sequence 批改为 1 如果心愿它显示为所有用户的登录页面。

October 4, 2021 · 1 min · jiezi

关于odoo:Odoo-14-中的-OWL-扩展和修补现有的-OWL-组件

OWL 组件介绍OWL 组件与通常的 Odoo JS 类大不相同,它们具备您相熟的自定义继承零碎。 首先它们是ES6 类,如果您不相熟 ES6 类,能够先学习ES6的内容 ES6 类基本上是 JavaScript 中现有的基于原型的继承的语法糖。在最根本的层面上,ES6 Class 是一个合乎基于原型继承的构造函数。ES6 类依然有 Object.prototype! 基于类和基于原型的继承之间最重要的区别在于,类定义了能够在运行时实例化的类型,而原型自身就是一个对象实例。要应用 Odoo 14 现有的 OWL 组件,先理解一些根本的概念。 class Component { constructor(name) { this.name = name; } render() { console.log(`${this.name} renders itself.`); } // Getter/setter methods are supported in classes, // similar to their ES5 equivalents get uniqueId() { return `${this.name}-test`; }}能够应用关键字继承类 extends 并用 super 调用父函数。 class MyBetterComponent extends Component { constructor(name) { super(name); // call the super class constructor and pass in the name parameter } render() { console.log(`${this.name} with id ${this.uniqueId} render itslef better.`); }}let comp = new MyBetterComponent('MyBetterComponent');comp.render(); // MyBetterComponent with id这是规范的 ES6 super 关键字,不要将它与_super 框架内构建的 Odoo函数混同。 ...

September 8, 2021 · 1 min · jiezi

关于odoo:未指定标题的文章

介绍新版本的odoo开始缩小workflow的应用,举荐应用workflow-ish的形式来解决工作流过程很多模块中还是应用到工作流,这里我记录一个简略的实例,欢送大家给出倡议。在本实例中工作流能够分为两个局部,一部分是“view视图”,一部分是“model办法”和相干的“流程字段”定义流程流转字段state = fields.Selection([ ('draft', '草稿'), ('read', '已阅'), ('write', '已写心得'), ('submit', '已上传心得')], string='Status', default='draft', readonly=True, copy=False, track_visibility='onchange')Selection 是一个多值抉择的字段类型,外面能够定义一个数组集。 odoo工作流String 是一个字段前台显示的值。default 是一个默认的初始的状态新创建数据后会默认加载这个状态初始值。track_visibility 流程变更可见性。readonly 是定义改状态值是否只读。定义工作流程的 def@api.onedef button_done(self): self.state = 'read' self.message_post('变更——————草稿 ——> 已阅', subtype='mail.mt_note')@api.onedef button_confirm(self): self.state = 'submit' self.message_post('变更——————已写心得 ——> 已上传心得', subtype='mail.mt_note') for rel in self.employee_ids: domain = [('id', '=', rel.id)] employee = self.env['files.employee'].search(domain) data = { 'name': employee.name, 'email': employee.work_email, 'event_id': self.id, 'wx_number': employee.wx_number, } self.env['activity.registration'].create(data)定义页面的 View<record model="ir.ui.view" id="view_activity_form"> <field name="name">activity.event.form</field> <field name="model">activity.event</field> <field name="arch" type="xml"> <form string="党员流动"> <header> <button string="流动已阅" name="button_done" states="draft" type="object" class="oe_highlight" groups="base.group_user"/> <button string="已上传流动心得" name="button_confirm" states="read" type="object" class="oe_highlight" groups="base.group_user"/> <field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/> </header> <sheet>states="draft" 是button显示与否的判断条件,如果值是这个值,则改button显示可见,即可用。class="oe_highlight" 是引入的 button 的款式,可自定义款式并引入。name="button_done" 是调用模型中的办法字段,如该办法调用后盾 def button_done(self) 办法。string="流动已阅" String是该状态按钮显示的值,最好定义为英文,而后进行国际化i18n翻译。<field name="state"... 是工作流程流转的状态值显示,到哪个阶段显示到哪个阶段的值。widget="statusbar" 款式成果展现。

August 26, 2021 · 1 min · jiezi

关于odoo:Odoo-14-Centos-7-安装教程

更新零碎 sudo yum update -ysudo yum install epel-release装置Python3 sudo yum install -y python3 python3-devel设置Python3 alternatives --install /usr/bin/python python /usr/bin/python2 50alternatives --install /usr/bin/python python /usr/bin/python3.6 60alternatives --config python修复Yum因为Yum要应用Python2的,所以要修复一下 cat /usr/bin/yum#!/usr/bin/python2.7cat /usr/libexec/urlgrabber-ext-down#!/usr/bin/python2.7增加odoo用户 sudo useradd -m -U -r -d /opt/odoo -s /bin/bash odoo增加零碎依赖包 sudo yum install git gcc wget nodejs libxslt-devel bzip2-devel openldap-devel libjpeg-devel freetype-devel装置设置PostgresqlOdoo14须要Postgresql 10以上 # 装置 RPM 仓库:sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 装置 PostgreSQL:sudo yum install -y postgresql12-server# 初始化数据库并设置自启动:sudo /usr/pgsql-12/bin/postgresql-12-setup initdbsudo systemctl enable postgresql-12sudo systemctl start postgresql-12创立数据库用户 ...

May 9, 2021 · 1 min · jiezi

关于odoo:Odoo-14开发者指南第二章-管理Odoo服务端实例

全书残缺目录请见:Odoo 14开发者指南(Cookbook)第四版 在第一章 装置Odoo开发环境中,咱们学习了如何应用源码中所带的规范外围插件配置Odoo实例。本章次要解说如何对Odoo实例增加非核心或自定义插件。在Odoo中,能够通过多个目录加载插件。此外,举荐应用独自的目录加载第三方插件或自定义的插件,以防止与Odoo外围模块产生抵触。甚至Odoo企业版也是一种类型的插件目录,须要像加载一般插件目录那样对其进行加载。 本章中,咱们将解说如下内容: 配置插件门路标准化你的实例目录布局装置及降级本地插件模块通过GitHub装置插件模块对插件利用批改利用及尝试倡议的拉取申请无关用语 本书中,咱们会穿插应用插件(add-on)、模块(module)、利用(app)或插件模块(add-on module)。它们都是指可通过用户界面在Odoo中装置的Odoo利用或扩大利用。 配置插件门路通过addons_path参数的配置,能够在 Odoo 中加载本人的插件模块。在Odoo初始化一个新数据库时,它会在addons_path配置参数中给定的这些目录中搜寻插件模块。addons_path会在这些目录中搜寻潜在的插件模块。 addons_path中所列出的目录预期应蕴含子目录,每个子目录是一个插件模块。在数据库初始化实现后,将可能装置这些目录中所给出的模块。 筹备工作这一部分假设你曾经筹备好了实例并生成了配置文件,如在第一章 装置Odoo开发环境在一个文件中存储实例配置一节所形容。Odoo的源码寄存在~/odoo-dev/odoo中,而配置文件寄存在~/odoo-dev/myodoo.cfg中。 如何配置...按如下步骤在实例的addons_path中增加~/odoo-dev/local-addons目录: 编辑你的实例配置文件,即 ~/odoo-dev/myodoo.cfg。定位到以addons_path =结尾的一行,默认应该会看到如下内容: addons_path = ~/odoo-dev/odoo/addons译者注:以后默认生成的配置文件中为绝对路径 批改该行,增加一个逗号(英文半角),并接你想想要增加为addons_path的目录名称,如以下代码所示: addons_path = ~/odoo-dev/odoo/addons,~/odoo-dev/local-addons在终端中重启实例 $ ~/odoo-dev/odoo/odoo-bin -c my-instance.cfg运行原理...在重启 Odoo 时,会读取配置文件。addons_path变量的值应为一个逗号分隔的目录列表。可承受相对路径,但它们是绝对于当前工作目录的,因而应在配置文件中尽量避免。 至此,咱们仅在Odoo中列出了插件目录,但~/odoo-dev/local-addons中尚不存在插件模块。即便在该目录中新增了插件模块,Odoo也不会在用户界面中显示这一模块。为此,你须要执行一个额定的操作,在下一部分更新插件模块列表中会进行解说。 这背地的起因是在初始化新数据库时,Odoo在可用模块中主动列举了自定义模块,但如若在数据库初始化之后新增模块,就须要像更新插件模块列表一节中那样手动更新可用模块列表。扩大常识...在首次调用 odoo-bin脚本来初始化新数据库时,能够传递一个带逗号分隔目录列表的--addons-path命令行参数。这会以所提供插件门路中所找到的所有插件来初始化可用插件模块列表。这么做时,要显式地蕴含根底插件目录(odoo/odoo/addons)以及外围插件目录(odoo/addons)。与后面稍有不同的是本地插件目录不能为空(译者注:请先浏览上面的小贴士),它必须要至多蕴含一个子目录,并蕴含插件模块的最小化构造。 在第三章 创立Odoo插件模块中,咱们会来看如何编写你本人的模块。同时,这里有一个生成内容来满足Odoo要求的快捷版黑科技: $ mkdir -p ~/odoo-dev/local-addons/dummy$ touch ~/odoo-dev/local-addons/dummy/__init__.py$ echo '{"name": "dummy", "installable": False}' > \~/odoo-dev/local-addons/dummy/__manifest__.py你能够应用--save选项来保留门路至配置文件中: $ odoo/odoo-bin -d mydatabase \--addons-path="odoo/odoo/addons,odoo/addons,~/odoo-dev/local-addons" \--save -c ~/odoo-dev/my-instance.cfg --stop-after-init本例中,应用相对路径不会有问题,因为它们会在配置文件中转化为绝对路径。 注:因为Odoo仅当从命令行中设置门路时在插件门路的目录中查看插件,而不是在从配置文件中加载门路的时候,dummy已不再必要。因而,你能够删除它(或保留到你确定不须要新建一个配置文件时)。标准化你的实例目录布局咱们举荐你在开发和生产环境都应用类似的目录布局。这一标准化会在你要执行运维时体现出用途,它也会缓解你日常工作的压力。 这一部分创立将类似生命周期或类似用处的文件分组放在标准化子目录中的目录构造。 仅在心愿以类似的文件构造治理开发和生产环境时才须要学习本节。如果不须要,能够跳过本节。此外,无微妙严格依照本节中雷同的目录构造。请自在依照本人的需要来调整这一构造。 如何标准化...创立所举荐实例布局,须要执行如下步骤: 为每个实例创立一个目录: $ mkdir ~/odoo-dev/projectname$ cd ~/odoo-dev/projectname在名为env/的子目录中创立一个Python虚拟环境对象: $ python3 -m venv env创立一些子目录,如下: ...

April 28, 2021 · 2 min · jiezi

odoo-js文件被替换

本打算在 from_controller.js 文件打个断点调试,却发现在chorm的sources下找不到该文件。 去看了web下的template.xml文件,发现form_controller.js正常引用了,并且所有的表单操作也是正常的,说明这个js的方法确实是存在的,只是这些方法去哪了呢? 全局搜索一下关键词。 可以看到在这个模块里, form_controller.js 通过replace被替换掉了。 进入这个文件发现所有的form_controller.js的方法都在这里边 。

September 10, 2019 · 1 min · jiezi

在-Odoo-模块安装后执行指定动作

在一个模块被安装之后,我们可能会希望它可以执行一些动作,例如打开某个菜单页面,打开某个网址,或者执行一些数据的初始化和处理等,我们可以借助 Odoo 的 ir.actions.todo 类型的动作来实现这个需求。 如果安装过 website 模块的话,应该会注意到在安装完毕之后页面跳转到了主题选择页面了,选择完主题后(主题也是一个模块,对应的主题模块会被安装)会跳转到网站首页,下面就是主题模块安装后跳转到首页的动作定义: <?xml version="1.0" encoding="utf-8"?><odoo> <record id="action_website" model="ir.actions.act_url"> <field name="name">Website</field> <field name="url">/</field> <field name="target">self</field> </record> <record id="base.open_menu" model="ir.actions.todo"> <field name="action_id" ref="action_website"/> <field name="state">open</field> </record></odoo>首先定义了一个跳转到首页的 act_url 动作,然后定义了一个 todo 类型的动作,并且在该动作的定义中指定 action_id(要执行的动作)为前面定义的动作。 在 todo 类型动作中所指定的动作是不限类型的,可以是窗口动作(act_window),服务器动作(server),也可以是客户端动作(client)以及打开 URL 的动作(act_url)。 其中 state 为该动作的状态,当一个动作被执行后,会被置为 done,之后便不会被触发。

April 24, 2019 · 1 min · jiezi

odoo12主题样式模块

odoo12主题样式模块图标形式显示菜单目录的结构图标形式显示菜单:https://apps.odoo.com/apps/th…12的基本样式结构:https://www.odoo.com/apps/the…

April 3, 2019 · 1 min · jiezi

odoo部署遇到的问题 yaml.parser.ParserError

ERROR: yaml.parser.ParserError: while parsing a block mapping in “./docker-compose.yml”, line 15在写docker-compose.yml文件version: ‘2’services: # PostgreSQL mydb: image: postgres:10 ports: - “5432:5432” environment: - POSTGRES_DB=postgres - POSTGRES_USER=odoo - POSTGRES_PASSWORD=odoo volumes: - odoo-db-data:/var/lib/postgresql/data # Odoo web web: build: context: ../odoo_demo dockerfile: Dockerfile hostname: web command: ./docker_run_web.sh volumes: - ../odoo_demo:/app # mount current directory inside container - odoo-web-data:/app/odoo-web-db # 把此路径/app/odoo-ee-web-db配置到odoo conf data_dir参数中 ports: - “8069:8069” # set up links so that web knows about db, rabbit and redis depends_on: - mydbvolumes: odoo-web-data: odoo-db-data:文件写完运行docker-compose up -d报错:ERROR: yaml.parser.ParserError: while parsing a block mapping in “./docker-compose.yml”, line 15, column 5expected <block end>, but found ‘<block mapping start>’ in “./docker-compose.yml”, line 25, column 4查看发现问题(vim)原因文件内块对齐有问题,使用notepad++打开查看如下:volumes: - ../odoo_demo:/app # mount current directory inside container - odoo-web-data:/app/odoo-web-db # 把此路径/app/odoo-ee-web-db配置到odoo conf data_dir参数中解决办法:在下面这句话前面添加两个空格,使他能和上面保持对其 - odoo-web-data:/app/odoo-web-db # 把此路径/app/odoo-ee-web-db配置到odoo conf data_dir参数中 ...

March 18, 2019 · 1 min · jiezi

odoo视图继承

简介继承在odoo里可以通过继承的方式来改写已经存在的view对比view的定义视图定义中写法多了inherit_idinherit_id指向要改写的view<field name=“inherit_id” ref=“id_category_list”/>在arch里用xpath定位改写的元素<!– 改写 ibuilding list 列表视图 –><record id=“building_list_view” model=“ir.ui.view”> <field name=“name”>building.list.view</field> <field name=“model”>ibuilding.list</field> <field name=“inherit_id” ref=“building_list”/> <field name=“arch” type=“xml”> <!– 找到ids字段,在其后添加idea_id字段 –> <xpath expr="//field[@name=‘ids’]" position=“after”> <field name=“idea_id” string=“Number of ideas”/> </xpath> <!– 找到 upload 字段,在其后添加idea_ids字段 –> <xpath expr="//field[@name=‘upload’]" position=“replace”> <field name=“download” string=“下载一个文件”/> </xpath> </field></record>注意找到的元素必须是一个,如果定位出多个元素或者是空,都会报错。expr Xpath表达式用来选择父视图中的某个元素,如果没找到或找到多个元素会抛出一个异常position定位有如下选择inside 在内部结尾插入元素replace 替换元素before 在之前插入元素after 在其后插入元素attributes 修改xml的属性当仅匹配一个field时,erpr表达式可以简化如下<xpath expr="//field[@name=‘upload’]" position=“replace”> <field name=“download” /></xpath><field name=“upload” position=“replace”> <field name=“download” /></field>

March 15, 2019 · 1 min · jiezi

odoo 国际化翻译

翻译功能简述每个模块的翻译文件放在该模块目录下i18n目录里。模块内相关字符串一般用英语写成,然后通过翻译模板导出功能,导出一个翻译模板po文件。翻译人员使用翻译软件(poedit)进行翻译后,产生对应语言po文件,再放入i18n目录下供odoo加载。po文件的文件名规则一般由对应语言缩写或语言_国家组成,如中文为zh.po或zh_CN.po这一步实现很简单,只需要在odoo中实现翻译成中文即可在已有的模块中要把因为页面翻译为中文页面,如下打开开发者模式点击设置在菜单中找到翻译,点击选择导出翻译语言选择“简体中文”文件格式选择po文件要导出的应用就是选择你要翻译的模块点击导出并下载po文件,第一步就完成了在你要翻译的模块下新建一个问价夹,文件命名为“i18n”重启你应用并更新就可以查看效果咯

March 14, 2019 · 1 min · jiezi

odoo导入功能二开

原来有的导入功能相信很多小伙伴对其功能不是很满意,不过没关系,我们可以二开啊,把它的功能改造成你想要的样子,接下来让我们看看怎么办吧例如我想把员工导入功能中添加上用户同步注册功能首先,我要找到原模块中导入时调用的模型——importUser.py文件找到这个文件之后打开 HtkjtImport 类,该类继承import基础模块class HtkjtImport(models.TransientModel): _inherit = “base_import.import"在该类下面找到 do 方法,将其重写当然咯,重写该方法或者其他方法都可以,不一定就选择这个代码风格规范一点的也可以自己新建一个方法,然后调用就可以了@api.multidef do(self, fields, columns, options, dryrun=False):self.ensure_one()self._cr.execute(‘SAVEPOINT import’)try: data, import_fields = self._convert_import_data(fields, options) # Parse date and float field data = self._parse_import_data(data, import_fields, options)except ValueError as error: return { ‘messages’: [{ ’type’: ’error’, ‘message’: pycompat.text_type(error), ‘record’: False, }] }_logger.info(‘importing %d rows…’, len(data))name_create_enabled_fields = options.pop(’name_create_enabled_fields’, {})model = self.env[self.res_model].with_context(import_file=True, name_create_enabled_fields=name_create_enabled_fields)import_result = model.load(import_fields, data)_logger.info(‘done’)# If transaction aborted, RELEASE SAVEPOINT is going to raise# an InternalError (ROLLBACK should work, maybe). Ignore that.try: if dryrun: self._cr.execute(‘ROLLBACK TO SAVEPOINT import’) # cancel all changes done to the registry/ormcache self.pool.reset_changes() else: self._cr.execute(‘RELEASE SAVEPOINT import’)except psycopg2.InternalError: pass# 导入成功后更新插入映射列if import_result[‘ids’] and options.get(‘headers’): BaseImportMapping = self.env[‘base_import.mapping’] for index, column_name in enumerate(columns): if column_name: # Update to latest selected field exist_records = BaseImportMapping.search( [(‘res_model’, ‘=’, self.res_model), (‘column_name’, ‘=’, column_name)]) if exist_records: exist_records.write({‘field_name’: fields[index]}) else: BaseImportMapping.create({ ‘res_model’: self.res_model, ‘column_name’: column_name, ‘field_name’: fields[index] })for da in data: print(da[1]) print(da[3]) data = { ’name’: da[1], ‘display_name’: da[1], ’email’: da[3], } partner = self.env[‘res.partner’].create(data) print(partner.id) data = { ’login’: da[3], ‘password’: 123456, ‘partner_id’: partner.id, } user = self.env[‘res.users’].create(data)return import_result ...

March 14, 2019 · 1 min · jiezi

Odoo创建模块,模块基础学习

Odoo创建模块这里我先引用一下几篇文章,这里完整的实现了一个odoo的模块创建demohttps://segmentfault.com/a/11…https://segmentfault.com/a/11...https://segmentfault.com/a/11...https://segmentfault.com/a/11...https://segmentfault.com/a/11...https://segmentfault.com/a/11…首先创一个保存自己模块的目录 myaddons添加到插件路径中addons_path = addons,myaddons运行命令行参数python odoo-bin scaffold tudo myaddons确保激活了venv 模块的组成在 Python 中,每一个包(package)都包含一个 init.py 文件,而一个 Odoo 的模块,同时也是一个 Python 包,所以我们可以看到,生成的项目文件里已经包含了 init.py 这个文件,如果打开这个文件,你会看到里面引入了 controllers 和 models 这两个包,稍候我们会讲到这两个,这里先放一放。那么对于这个 init.py 文件,我们没什么特殊需求,是可以不用去理会的,就让它静静地躺在那里完成它的使命就好了。文件 manifest.py 用于声明一个 Odoo 模块以及指定它的元数据(metadata),文件里只包含了一个单独的 Python 字典,里面默认只列出了 9 项最基本的配置项,包含了模块(或应用)名,模块的简介和详细介绍,作者和网站,模块的所属分类、版本,还有就是这个模块依赖于其他的哪些 Odoo 模块,需要加载哪些数据文件以及演示数据。除了这里列出的配置项外,还有一些高级配置项,我们这里暂时不需要理会,后面用到之后将会进行详细的说明。接下来我们先讲一下 demo 和 security 这两个目录。前者是用于存放演示数据的,在 manifest.py 中就可以看到有引入该目录下的 demo.xml 文件,在使用演示模式时,初始化一些演示数据可以帮我们节省不少的时间;而后者通过名字就知道它的作用是跟安全相关的,目录下只有一个 ir.model.access.csv 文件,里面用于定义不同的角色组对应于不同模型的相关权限,包括读(read),写(write),创建(create)和删除(unlink)权限,拥有相关权限则为 1,反之为 0。我们刚提到了角色组,但是没有发现相关定义的位置,我们只要默认角色组的定义和模型权限定义在同一目录下就可以了,角色组的定义同样也是使用的 .xml 文件,在后面我们会有专门的一篇文章对角色组和权限进行讲解说明。下面要讲的是 Odoo 开发中的核心部分 MVC(同时也是大部分 Web 应用开发所采用的经典模式),MVC 分别代表的是 Model(模型)、View(视图)和 Controller(控制器)。有关 MVC 模式具体的概念和相关的知识,这里就不作详细讲解了,希望不了解的同学可以去找找相关的内容学习一下。这里简单说一下它们各自的用途,在 Model 中,我们定义一切和数据相关的东西,例如对应到数据库表字段的模型字段、各种外键关系以及操作数据的逻辑方法等。View 则是负责数据展示的,我们通过编写视图控制需要展示出来的数据以及以什么样的形式展示数据等,并且可以在视图上进行交互。Controller 则是在 Model 和 View 之间,负责响应用户操作,从 Model 中获取数据进行处理并返回到 View 中。安装模块打开开发者模式 更新本地模块列表更新完后就可以找到我们创建的odoogoedu模块进行安装注意模块的目录名称使用小写__manifest__.py 里的name 补充__manifest__.py 另外2个有用的参数’application’: True,‘sequence’: 1, ...

March 14, 2019 · 1 min · jiezi

odoo访问权限 (二. 记录规则)

记录规则通过记录规则可以灵活地设置权限。规则保存在ir.rule模型表里,需要设置关联某个模型,关联很多组,访问权限控制和domian。通过domain_force过滤出的一些记录来执行约束。例子:经理只能删除状态为’cancel’的客户线索。注意向many2many字段添加值的写法。<record id=“delete_cancelled_only” model=“ir.rule”> <field name=“name”>Only cancelled leads may be deleted</field> <field name=“model_id” ref=“crm.model_crm_lead”/> <field name=“groups” eval="[(4, ref(‘base.group_sale_manager’))]"/> <field name=“perm_read” eval=“0”/> <field name=“perm_write” eval=“0”/> <field name=“perm_create” eval=“0”/> <field name=“perm_unlink” eval=“1” /> <field name=“domain_force”>[(‘state’,’=’,‘cancel’)]</field></record>例子:只有经理可以编辑课程,如果没有经理,任何人都可以编辑security.xml<record id=“group_manager” model=“res.groups”><field name=“name”>todufiledu / 管理员</field></record><record id=“only_responsible_can_modify” model=“ir.rule”><field name=“name”>只有经理可以编辑</field><field name=“model_id” ref=“model_todo_file”/><field name=“groups” eval="[(4, ref(’todufiledu.group_manager’))]"/><field name=“perm_read” eval=“0”/><field name=“perm_write” eval=“1”/><field name=“perm_create” eval=“0”/><field name=“perm_unlink” eval=“1”/><field name=“domain_force”> [’|’, (‘responsible_id’,’=’,False), (‘responsible_id’,’=’,user.id)]</field></record>odoo设置员工能看自己新建的记录规则 经理能看所有记录的规则增加2个组组1 能看全部记录组2 增加只能看自己的记录增加一个经理能看所有记录的规则关联模型 res.partner规则填入 [(1,’=’,1)]组加入 全部记录组增加一个员工能看自己记录的规则关联模型 res.partner规则 [’|’,(‘user_id’,’=’,user.id),(‘id’,’=’,user.partner_id.id)]组加入 只能看自己记录组

March 14, 2019 · 1 min · jiezi

Odoo访问权限(一)

Odoo访问权限一四个ODOO权限管理层次一. Odoo 菜单级别: 即,不属于指定菜单所包含组的用户看不到该菜单。不安全,只是隐藏菜单,若用户知道菜单ID,仍然可以通过指定URL访问二. Odoo 对象级别: 即,对某个对象是否有‘创建,读取,修改,删除“的权限。OE中的对象可以简单理解为表对象,比如“客户”,“产品”,“销售订单”等都是对象三. Odoo 记录级别: 即,对对象表中的数据的访问权限。比如同样访问“客户”对象,业务员只能对自己创建的客户有访问的权限,而经理可以访问其所辖的业务员的所有“客户”对象,这里的访问也可以进一步明细到“创建,读取,修改,删除”的权限四. 字段级别: 即,一个对象或表上的某些字段的访问权限。比如产品的成本字段只有经理有读权限,比如订单上的单价字段只有经理才有修改的权限等。本章节介绍一二层次的权限在security文件夹下新建两个文件夹model_security.xmlir.model.access.csv用户组实例<?xml version=“1.0” encoding=“utf-8”?><odoo> <data noupdate=“0”> <record model=“ir.module.category” id=“module_category_activity”> <field name=“name”> 活动管理 </field> </record> <record model=“res.groups” id=“group_activity_user”> <field name=“name”> 用户 </field> <field name=“category_id” ref=“module_category_activity”/> </record> <record model=“res.groups” id=“group_activity_manager”> <field name=“name”> 管理 </field> <field name=“implied_ids” eval="[(4, ref(‘group_activity_user’))]"/> <field name=“category_id” ref=“module_category_activity”/> </record> </data></odoo>权限分配实例id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlinkaccess_activity_event_user,读权限,model_activity_event,group_activity_user,1,0,0,0access_activity_event_system_user,管理权限,model_activity_event,group_activity_manager,1,1,1,1access_activity_type_user,分类读权限,model_activity_type,group_activity_user,1,0,0,0access_activity_type_system_user,分类管理权限,model_activity_type,group_activity_manager,1,1,1,1id: 可以自定义,不能重复name: 自定义就可以model_id:id: model_模型名称。注意,这里要把“.”全部换成“_”,否则会报错。perm_read:读权限。有权限写‘1’,没权限写‘0’perm_write: 编辑权限。有权限写‘1’,没权限写‘0’perm_create: 创建权限。有权限写‘1’,没权限写‘0’perm_unlink: 删除权限。有权限写‘1’,没权限写‘0’重点注意要在__manifest__.py文件中引入以上新建的两个文件always loaded’data’: [‘security/activity_security.xml’,‘security/ir.model.access.csv’,‘views/views.xml’,‘views/templates.xml’,‘views/menus.xml’,‘data/activity_data.xml’,],最后安装或升级项目模块就可以试试效果了

March 14, 2019 · 1 min · jiezi

odoo12 工作流

介绍新版本的odoo开始减少workflow的使用,推荐使用workflow-ish的方式来处理工作流过程很多模块中还是使用到工作流,这里我记录一个简单的实例,欢迎大家给出建议。在本实例中工作流可以分为两个部分,一部分是“view视图”,一部分是“model方法”和相关的“流程字段”定义流程流转字段state = fields.Selection([ (‘draft’, ‘草稿’), (‘read’, ‘已阅’), (‘write’, ‘已写心得’), (‘submit’, ‘已上传心得’)], string=‘Status’, default=‘draft’, readonly=True, copy=False, track_visibility=‘onchange’)Selection 是一个多值选择的字段类型,里面可以定义一个数组集。odoo工作流String 是一个字段前台显示的值。default 是一个默认的初始的状态新创建数据后会默认加载这个状态初始值。track_visibility 流程变更可见性。readonly 是定义改状态值是否只读。定义工作流程的 def@api.onedef button_done(self): self.state = ‘read’ self.message_post(‘变更——————草稿 ——> 已阅’, subtype=‘mail.mt_note’)@api.onedef button_confirm(self): self.state = ‘submit’ self.message_post(‘变更——————已写心得 ——> 已上传心得’, subtype=‘mail.mt_note’) for rel in self.employee_ids: domain = [(‘id’, ‘=’, rel.id)] employee = self.env[‘files.employee’].search(domain) data = { ’name’: employee.name, ’email’: employee.work_email, ’event_id’: self.id, ‘wx_number’: employee.wx_number, } self.env[‘activity.registration’].create(data)定义页面的 View<record model=“ir.ui.view” id=“view_activity_form”> <field name=“name”>activity.event.form</field> <field name=“model”>activity.event</field> <field name=“arch” type=“xml”> <form string=“党员活动”> <header> <button string=“活动已阅” name=“button_done” states=“draft” type=“object” class=“oe_highlight” groups=“base.group_user”/> <button string=“已上传活动心得” name=“button_confirm” states=“read” type=“object” class=“oe_highlight” groups=“base.group_user”/> <field name=“state” widget=“statusbar” statusbar_visible=“draft,confirm,done”/> </header> <sheet>states=“draft” 是button显示与否的判断条件,如果值是这个值,则改button显示可见,即可用。class=“oe_highlight” 是引入的 button 的样式,可自定义样式并引入。name=“button_done” 是调用模型中的方法字段,如该方法调用后台 def button_done(self) 方法。string=“活动已阅” String是该状态按钮显示的值,最好定义为英文,然后进行国际化i18n翻译。<field name=“state”… 是工作流程流转的状态值显示,到哪个阶段显示到哪个阶段的值。widget=“statusbar” 样式效果展示。 ...

March 14, 2019 · 1 min · jiezi

odoo 模型与ORM

型号属性在/模型添加activity.py文件class ActivityEvent(models.Model): _name = ‘activity.event’ _inherit = ’event.event’ _rec_name = ’test_field’ # 字段 test_field = fields.Char(string=“字段名称”) # 多对多的关联表 employee_ids = fields.Many2many(‘files.employee’, ‘activity_event_files_employee_rel’, string=‘与会员工’) event_type_id = fields.Many2one( ‘activity.type’, string=‘Category’, readonly=False, states={‘done’: [(‘readonly’, True)]}, oldname=‘type’)model属性详解::类型_name唯一标识,类非继承父类时必须指定。_rec_name:数据显示名称,如设置则返回其指定的字段值,不设置默认显示字段为name的字段值,如无名字段则显示“模块名,ID”;详见BaseModel.name_get方法。_log_access:是否自动增加日志字段(create_uid,create_date,write_uid,write_date)默认为真。_auto:是否创建数据库对象默认为真,详见BaseModel._auto_init方法。_table:数据库对象名称缺。省时数据库对象名称与_name指定值相同(.替换为下划线)_sequence。:数据库id字段的序列。默认自动创建序列。_order:数据显示排序。所指定值为模型字段,按指定字段和方式排序结果集。例:_order =“create_date desc”:根据创建时间降序排列。可指定多个字段。不指定desc默认升序排列;不指定_order默认id升序排列。_constraints:自定义约束条件模型创建/编辑数据时触发,约束未通过弹出错误提示,拒绝创建/编辑。格式:: _constraints = [(method, ’error message’, [field1, …]), …]method检查方法。返回True | False error message:不符合检查条件时(方法返回False)弹出的错误信息[field1, …]:字段名列表,这些字段的值会出现在错误消息中。_sql_constraints:数据库约束。例:_sql_constraints = [ (’number_uniq’, ‘unique(number, code)’, ’error message’) ]会在数据库添加约束:CONSTRAINT number_uniq UNIQUE(number, code)_inherit。:单一继承值为所继承父类_name标识如子类不定义_name属性,则在父类中增加该子类下的字段或方法,不创建新对象;如子类定义_name属性,则创建新对象,新对象拥有父类所有的字段或方法,父类不受影响。格式:_inherit = ‘父类 _name’_inherits:多重继承子类通过关联字段与父类关联,子类不拥有父类的字段或方法,但是可以直接操作父类的字段或方法。格式:_inherits = {‘父类 _name’: ‘关联字段’}字段属性基础类型Char:字符型,使用尺寸参数定义字符串长度。Text:文本型,无长度限制。Boolean:布尔型(真,假)Interger:整型Float:浮点型,使用数字参数定义整数部分和小数部分位数如。digits=(10,6)Datetime:日期时间型Date:日期型Binary:二进制型selection:下拉框字段。 例:state = fields.Selection([(‘draft’, ‘Draft’),(‘confirm’, ‘Confirmed’),(‘cancel’, ‘Cancelled’)], string=‘Status’)Html:可设置字体格式,样式,可添加图片.关系类型1. One2many:一对多关系。定义:otm = fields.One2many(“关联对象 _name”, “关联字段”,string=“字段显示名”,…)例:analytic_line_ids = fields.One2many(‘account.analytic.line’, ‘move_id’, string=‘Analytic lines’)“2. Many2one定义:mto = fields.Many2one(“关联对象 _name”, string=“字段显示名”,…)可选参数:ondelete,可选值为’级联’和’空’,缺省为空表示一个端删除时多端是否级联删除。3. Many2many定义:mtm = fields.Many2many(“关联对象 _name”, “关联表/中间表”,“关联字段1”,“关联字段2”,string=“字段显示名”,…)其中,关联字段,关联表/中间表可不填,中间表缺省为:表1_表2_rel例:partner_id= fields.Many2many(“res.partner”, string=“字段显示名”,…)“复杂类型参数readonly: 是否只读,缺省值False。required: 必填填,缺省值Falsse。string: 字段显示名,任意字符串。default: 字段默认值domain: 域条件,缺省值[]。在关系型字段中,domain用于过滤关联表中数据。help: 字段描述,鼠标滑过时提示。store: 是否存储于数据库。结合计算和相关使用。例:sale_order = fields.One2many(“sale.order”, “contract_id”,string=“销售订单”, domain=[(‘state’,’=’,‘sale’)])compute:字段值由函数计算,该字段可不储存于数据库。例:amount = fields.Float(string=“金额总计”, compute=‘_compute_amount’,store=True)_compute_amount为计算函数。related:字段值引用关联表中某字段。以下代码表示:company_id引用hr.payroll.advice中company_idadvice_id = fields.Many2one(‘hr.payroll.advice’, string=‘Bank Advice’)company_id = fields.Many2one(‘res.company’, related=‘advice_id.company_id’, string=‘Company’, store=True) ...

March 13, 2019 · 1 min · jiezi

odoo 模型继承

在odoo中有两种模型的继承机制(传统方式和委托继承方式)重点:在__manifest__.py中找到depends,加上要继承的模块’depends’: [‘account’]注意继承的模型所在addon需要在本addon里添加依赖,不然会报一个TypeError: Model ‘xxx’ does not exist in registry 错误。传统方式能够添加字段 改写字段定义 添加约束 添加或改写方法共有两种写法 1 类继承 2 原型继承类继承_name = ’event.registration’_inherit = ’event.registration’_name和_inherit的模型名一致,都为’event.registration’, 此时_name可以省略不写。类继承不会创建新的模型,能够直接修改模型定义,新加的字段会在原表中添加,数据库中没有新的表生成。例子class model_1(models.Model): _name = ‘activity.registration’ class model_2(models.Model): _inherit = ’event.registration’ event_id = fields.Many2one( ‘activity.event’, string=‘Event’, required=True, readonly=True, states={‘draft’: [(‘readonly’, False)]})原型继承_name = ‘activity.registration’_inherit = ’event.registration’_name 和 _inherit 的模型名不同。 相当于把模型 event 的属性(字段 方法等)copy了一份,重新创建一个新的模型 activity,新的表里有模型 event 的字段。例子class ActivityRegistration(models.Model): _name = ’event.registration’ name = fields.Char() def say(self): return self.check(“event”) def check(self, s): return “This is {} record {}".format(s, self.name) class ActivityRegistration(models.Model): _name = ‘activity.registration’ _inherit = ’event.registration’ def say(self): return self.check(“activity”)支持多重继承,用列表表示 _inherit = [‘mail’, ‘resource’]委托继承class NewModel(): _name = “new.model” _inherits = {‘模型1’: ‘关联字段1’,‘模型2’: ‘关联字段2’}支持多重继承,并提供透明的子模型字段访问方法,好像模型有子模型字段例子class Child0(models.Model): _name = ‘delegation.child0’ field_0 = fields.Integer() class Child1(models.Model): _name = ‘delegation.child1’ field_1 = fields.Integer() class Delegating(models.Model): _name = ‘delegation.parent’ _inherits = { ‘delegation.child0’: ‘child0_id’, ‘delegation.child1’: ‘child1_id’, } child0_id = fields.Many2one(‘delegation.child0’, required=True, ondelete=‘cascade’) child1_id = fields.Many2one(‘delegation.child1’, required=True, ondelete=‘cascade’)这种继承只能继承字段,其他方法不继承可以读写子模型的字段record.field_1record.field_2record.write({‘field_1’: 4})如果子模型里的字段重复,只能看到_inherits第一个子模型的字段 ...

March 13, 2019 · 1 min · jiezi

odoo基础数据加载

odoo 基础数据加载这里介绍的odoo基础数据加载分两种方式,一种是演示数据加载,一种是默认数据加载,下面就是详细介绍首先,当然是创建一个date文件夹项目目录,右键自定义一个文件夹XML数据定义格式 <record id=“building_type0” model=“building.document.folder”> <field name=“name”>局集团党委文件</field> </record> <record id=“activity_type1” model=“building.document.folder”> <field name=“name”>总支部文件</field> </record> <record id=“building_type2” model=“building.document.folder”> <field name=“name”>支部文件</field> </record>model里填 modelclass 的 name 值id里填外部标识(external-identifier),是odoo中用来标注某条数据库记录的唯一标示符注意:可以在web设置里查看所有的外部标识。内部field就是定义具体记录的列名和值,可以有多个列,如下: <record id=“documents_hr_documents_facet” model=“documents.facet”> <field name=“name”>Documents</field> <field name=“sequence”>6</field> <field name=“folder_id” ref=“documents_hr_folder”/> </record> <record id=“documents_internal_template_facet” model=“documents.facet”> <field name=“name”>Templates</field> <field name=“sequence”>6</field> <field name=“folder_id” ref=“documents_internal_folder”/> </record>数据文件需在__manifest_.py data或demo字段里列出,才能在模块安装更新后正确的加载’data’: [ ‘security/security.xml’, ‘security/ir.model.access.csv’, ‘assets.xml’, ‘views/views.xml’, ‘views/templates.xml’, ‘data/building_data.xml’,],# ‘demo’: [ ‘demo/demo.xml’,],demo数据只在勾选演示数据后才会加载(only loaded in demonstration mode)data数据在系统启动后会自动进行加载(always loaded)

March 12, 2019 · 1 min · jiezi

odoo发送信息到微信

@TOCodoo发送信息到微信在odoo平台中进行项目开发的时候有时会用到跟其他平台对接发送信息。这里我写一个odoo发送信息到企业微信中的例子。如果你按照下面的做有问题的话可以留言!corpID:微信公众号中企业IDagentId :首先在 微信公众号-应用-创建应用 下创建应用,创建好后会显示 agentIdsecret:首先在 微信公众号-应用-创建应用 下创建应用,创建好后会显示 secretnumbers: numbers是选中要发送的人员账户字符串数据;例子—— ‘Quan|XiaoXin’,多个人的话可以用“|”分隔拼接@api.multidef send_activity_meg(self):numbers = [re.wx_number + ‘|’ for re in self.registration_ids]# 以下是获取微信公众号的三个数据corpID = ‘wwd0fa7b2d99da5810’agentId = ‘1000003’secret = ‘I3NLAkheWsBLZdAc-akf24-iGthbknmwgVntV4XESHw’client = WeChatClient( corpID, secret)client.message.send_text(agentId, numbers, ‘这里是要发送的信息数据’)

March 8, 2019 · 1 min · jiezi

odoo打包下载

view 视图中下载按钮的编辑 <record id=“action_download_zip” model=“ir.actions.server”> <field name=“name”>附件打包下载</field> <field name=“model_id” ref=“model_activity_event”/> <field name=“binding_model_id” ref=“model_activity_event”/> <field name=“state”>code</field> <field name=“code”> if records: action = { ’name’: ‘Visit Webpage’, ’type’: ‘ir.actions.act_url’, ‘url’: ‘/document/zip/’+str(records.download_zip()), ’target’: ‘self’, } </field> </record>model 中获取需要下载的文件的ID,并返回字符串集合打包下载的方法@api.multidef download_zip(self): dones = self.env[‘ir.attachment’].search([(‘res_model’, ‘=’, ‘activity.event’), (‘res_id’, ‘=’, self.id)]) file_ids = ’’ for x in dones: file_ids = file_ids + str(x.id) + ‘,’ print(file_ids) return { file_ids }controller.py中的打包下载引用和方法,如下代码# -- coding: utf-8 --import base64import ioimport jinja2import jsonimport loggingimport osimport sysimport zipfileimport timeimport werkzeugimport werkzeug.exceptionsimport werkzeug.utilsimport werkzeug.wrappersimport werkzeug.wsgifrom odoo import httpfrom odoo.http import content_disposition, dispatch_rpc, request, \ serialize_exception as serialize_exception, Responsefrom odoo.exceptions import AccessError, UserError, AccessDeniedfrom odoo.models import check_method_namefrom odoo.service import db, security_logger = logging.getLogger(name)if hasattr(sys, ‘frozen’): # When running on compiled windows binary, we don’t have access to package loader. path = os.path.realpath(os.path.join(os.path.dirname(file), ‘..’, ‘views’)) loader = jinja2.FileSystemLoader(path)else: loader = jinja2.PackageLoader(‘odoo.addons.web’, “views”)env = jinja2.Environment(loader=loader, autoescape=True)env.filters[“json”] = json.dumps# 1 week cache for asset bundles as advised by Google Page SpeedBUNDLE_MAXAGE = 60 * 60 * 24 * 7DBNAME_PATTERN = ‘^[a-zA-Z0-9][a-zA-Z0-9.-]+$’#———————————————————-# Odoo Web helpers#———————————————————-db_list = http.db_listdb_monodb = http.db_monodbclass DownloadAll(http.Controller): def _get_file_response(self, id, filename=None, field=‘datas’, share_id=None, share_token=None): """ returns the http response to download one file. """ status, headers, content = request.registry[‘ir.http’].binary_content( id=id, field=field, filename=filename, related_id=share_id, access_token=share_token, access_mode=‘documents_share’, download=True) if status == 304: response = werkzeug.wrappers.Response(status=status, headers=headers) elif status == 301: return werkzeug.utils.redirect(content, code=301) elif status != 200: response = request.not_found() else: content_base64 = base64.b64decode(content) headers.append((‘Content-Length’, len(content_base64))) response = request.make_response(content_base64, headers) return response def _make_zip(self, name, attachments): “““returns zip files for the Document Inspector and the portal. :param name: the name to give to the zip file. :param attachments: files (ir.attachment) to be zipped. :return: a http response to download a zip file. "”” stream = io.BytesIO() try: with zipfile.ZipFile(stream, ‘w’) as doc_zip: for attachment in attachments: if attachment.type in [‘url’, ’empty’]: continue filename = attachment.datas_fname doc_zip.writestr(filename, base64.b64decode(attachment[‘datas’]), compress_type=zipfile.ZIP_DEFLATED) except zipfile.BadZipfile: _logger.exception(“BadZipfile exception”) content = stream.getvalue() headers = [ (‘Content-Type’, ‘zip’), (‘X-Content-Type-Options’, ’nosniff’), (‘Content-Length’, len(content)), (‘Content-Disposition’, content_disposition(name)) ] return request.make_response(content, headers) @http.route([’/document/zip/<string:file_ids>’], type=‘http’, auth=“public”) def _get_zip(self, file_ids=None, *args, **kwargs): “““route to get the zip file of the selection in the document’s Kanban view (Document inspector). :param file_ids: if of the files to zip. :param zip_name: name of the zip file. "”” file_ids = file_ids[2:-3] print(file_ids) timestamp = time.strftime(’%Y%m%d%H%M%S’,time.localtime(time.time())) zip_name = ‘activity-’ + timestamp + ‘.zip’ ids_list = [int(x) for x in file_ids.split(’,’)] print(ids_list) env = request.env return self._make_zip(zip_name, env[‘ir.attachment’].browse(ids_list)) ...

March 8, 2019 · 2 min · jiezi

Centos7 安装 Odoo11

Centos7 安装 Odoo111 安装python3.6Centos7 基于稳定性考虑安装的是python2.7,而且默认的官方 yum 源中不提供 Python 3 的安装包,所以我们要先换一个提供python3的yum源– IUS 。 1、IUS软件源依赖与epel软件源包,首先要安装epel软件源包sudo yum install epel-release2、安装IUS软件源sudo yum install https://centos7.iuscommunity.org/ius-release.rpm3、安装python3.6sudo yum install python36usudo yum -y install python36u-develsudo yum -y install python36u-pip2 安装配置PostgreSQL数据库2.1 安装1、安装sudo yum install -y postgresql-server2、初始化service postgresql initdb3、启动服务systemctl start postgresql4、设置开机运行服务systemctl enable postgresql2.2 配置1、创建数据库和角色# 切换到 postgres 用户sudo su - postgres# 登录PostgreSQL控制台psql# 系统提示符会变为"postgres=#",表示这时已经进入了数据库控制台# 创建数据库用户dbuserCREATE USER dbuser WITH PASSWORD ‘password’ ENCODING=‘UTF8’;# 创建用户数据库CREATE DATABASE exampledb OWNER dbuser;# 将exampledb数据库的所有权限都赋予dbuserGRANT ALL PRIVILEGES ON DATABASE exampledb to dbuser;# 使用\q命令退出控制台(也可以直接按ctrl+D)\q如果在创建数据库时报如下错误:ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)则通过如下方式解决update pg_database set datallowconn = TRUE where datname = ’template0’; \c template0update pg_database set datistemplate = FALSE where datname = ’template1’; drop database template1;create database template1 with encoding = ‘UTF8’ LC_CTYPE = ’en_US.UTF-8’ LC_COLLATE = ’en_US.UTF-8’ template = template0;update pg_database set datallowconn = TRUE where datname = ’template1’;\c template1update pg_database set datallowconn = FALSE where datname = ’template0’;——————— 作者:东方-phantom 来源:CSDN 原文:https://blog.csdn.net/hkyw000/article/details/52817422 版权声明:本文为博主原创文章,转载请附上博文链接!2、配置这一步要修改两个配置文件:pg_hba.conf 和 postgresql.conf 。可以通过以下命令找到文件位置:sudo find / -name ‘filename’首先修改 pg_hba.conf :添加下面这行(这行是用于可远程连接的,如果想限制数据库只能本地访问的话,跳过)host all all 0.0.0.0/0 md5找到并修改下面这两行local all all peer md5host all all 127.0.0.1/32 ident md5修改 postgresql.conf (用于可远程连接,如不需要可调过):添加下面这行listen_addresses = ‘*‘修改完成之后,重启服务:systemctl restart postgresql至此,PostgreSQL 安装配置完成!3 安装 node.js 和 less插件Odoo 前端依赖 node.js 和 less,用以下命令安装:sudo yum install -y nodejssudo npm install -g less less-plugin-clean-css4 安装依赖yum install wkhtmltopdfyum install python-devel openldap-develyum install libxslt-devel libxml++-devel libxml2-develyum install gcc5 安装Odoo11这里我们用 pipenv 安装,首先安装 pipenvpip3.6 install pipenv拉取odoo11 代码后,在项目根目录创建虚拟环境并安装依赖pipenv –python python3.6 install -r requirments.txt安装时会有一个 win32 的模块安装失败,不用管,这个是windows系统开发时需要依赖的包。安装完成之后,创建一个 odoo 配置文件: odoo.conf 。 内容如下:[options];模块路径addons_path = odoo/addons,odoo/myaddons;超级管理员密码admin_passwd = admindb_host = localhostdb_port = 5432db_maxconn = 64;数据库名称db_name = ***;数据库用户db_user = ***;数据库密码db_password = ***然后运行如下命令启动 odoopython odoo-bin -c odoo.conf访问 127.0.0.1:8069 ,如果进入到odoo登录页面就说明安装成功了! ...

January 31, 2019 · 2 min · jiezi

Odoo 模块推荐——Web Dialog Size

好久不见,我又回来了,带着新的内容板块再次和大家见面啦~这是你没有见过的全新板块(自动播放喳喳辉发音)在新的内容板块里,我将会为大家推荐一些实用的 Odoo 模块,并且通过简单的实例来说明这些模块的使用方法和适用场景(可能会在某些时候虚构一些业务场景),除此之外我还将对部分模块的实现和源码进行简单的讲解和分析,毕竟会用不是我们的目的,知晓其核心才更有意义。今天就先推荐一个小模块吧,虽然这个模块很简单,但是却能带来很实在的用户体验上的提升。 备注名称Web Dialog Size 功能让用户可以放大弹窗到全屏宽,并且让弹窗可以拖动 商店地址点击前往商店中最高版本为 11.0仓库地址前往 GitHub仓库中最高版本为 12.0使用体验本次体验使用的 Odoo 版本是 12.0,不同版本之间可能会有细微差异,请以实际使用情况为准。模块安装之后不需要任何配置,这个模块对 Odoo 中的弹窗做了一些优化,为了看到效果我们需要找一个弹窗出来。在打开「开发者模式」后点击菜单「Update Apps List」就有一个弹窗出现:把注意力放在上图弹窗右上角的高亮处,在安装该模块前,高亮位置是没有这样的扩展图标的。在点击该图标后,弹窗的宽度发生了变化:同时扩展图标也变成了收缩图标,除了缩放图标和弹窗宽度的变化外,这个模块还让原本不能拖动的弹窗变得可以随意拖动了:适用场景上面只是简单的试用,并不能体现出这个模块的优点,那我们打开另一个弹窗再看一下效果吧:这是个人选项(在右上角下拉菜单里的「Preferences」)的弹窗,就签名(Signature)来说,在纵向高度不是很够的时候,如果横向宽度也不够宽的话,我们在富文本框内输入时,很容易就会换行,然后需要滚动文本去查看上面的内容,而把窗口放大到全屏宽之后,文本框内每行就能多显示一些字符了。又或者说在弹窗内有列表需要显示,而且字段相对较多,弹窗宽度不够就需要横向滚动列表,稍微有些麻烦,这时候将弹窗放大到全屏宽就能显示更多列的内容了。其实我觉得最有用的还是窗口拖动这个功能。不妨设想一个场景,你正在编辑一个表单页面上的 x2many 字段,你创建了一些这个字段的记录,在你又一次创建新记录并且在填写了一半的内容之后,想要看一下现在正在创建的这条记录是不是在前面已经创建过了,可是列表前面的几条数据刚好被弹窗遮挡住了,这时为了避免创建重复的数据,你不得不关闭弹窗去查看列表前面的记录,如果并没有创建过,前面填写的这么多内容就都白费了!而窗口可以拖动的话,就可以轻松地查看到被挡住的内容,然后你可以继续填写剩下的字段,舒服呀!对于我这种金鱼记忆的人来说,这个功能再好用不过了。实现浅析上面看完了怎么用,现在我们来看看怎么写。因为这是个对前端展现内容做修改的模块,核心部分基本上都在其 JS 代码中,所以我们直奔主题,打开 static/src/js/ 目录下的 JS 文件,一般情况下这种类型的模块其 JS 命名是和模块名一样的,在这个模块里就是 web_dialog_size.js 了。先来看看 willStart() 这个方法:willStart: function () { var self = this; return this._super.apply(this, arguments).then(function () { self.$modal.find(’.dialog_button_extend’).on(‘click’, self.proxy(’_extending’)); self.$modal.find(’.dialog_button_restore’).on(‘click’, self.proxy(’_restore’)); return config.done(function(r) { if (r.default_maximize) { self._extending(); } else { self._restore(); } }); });},在执行完 _super() 之后,这里只是简单地做了三件事:为扩展按钮添加点击事件,绑定方法 _extending()为收缩按钮添加点击事件,绑定方法 _restore()查询系统参数,判断弹窗是否默认为放大状态,然后执行相应的方法其中第 3 点中用到了 RPC 请求去调用模型的方法查询数据:var config = rpc.query({ model: ‘ir.config_parameter’, method: ‘get_web_dialog_size_config’,});打开模块的 models/ir_config_parameter.py 可以看到只有一个模型方法:@api.modeldef get_web_dialog_size_config(self): get_param = self.sudo().get_param return { “default_maximize”: const_eval( get_param(“web_dialog_size.default_maximize”, “False”)) }这个方法所做的就是查找系统参数中弹窗默认是否最大化的值,默认值为 False。划重点!当我们编写的前端内容需要从后台获取返回值,例如上面的获取配置信息,就可以像这个模块这样做,最后返回得到的是一个 Promise,可以使用 .then() 和 .done() 等方法链。下面再看看 opened() 这个方法:opened: function(handler) { return this._super.apply(this, arguments).then(function(){ if (this.$modal) { this.$modal.draggable({ handle: ‘.modal-header’, helper: false }); } }.bind(this));},这个方法将会在弹窗打开(open())之后执行,这里只做了一件事,让窗口可以拖动。这里是利用 jQuery UI 的 Draggable) 实现的。重点来了,Odoo 的前端用到的一个基础框架就是 jQuery UI),也就是说里面的 Widgets 和各种效果以及工具方法我们都可以在自定义 Widget 或编写扩展的时候用上,在准备实现某些相关的功能前,不妨先看看官方文档,说不定就省了很多的功夫呢 XD ...

January 17, 2019 · 1 min · jiezi