zoukankan      html  css  js  c++  java
  • odoo10基础

    参考文档 看云文档参考    思否ruter文档参考

    odoo开发,需要那些工具

    python
    postgresql
    node.js
    less (css是静态, less是动态)
    git

    运行odoo

    1 安装路径: /xx/xx
    2 /xx/xx/odoo-bin -c odoo-dev/odoo.conf & # odoo-dev/odoo.conf 配置文件
      -c 指定配置文件文件
      & 后台运行

    odoo技巧

    数据库管理:http://127.0.0.1:8069/web/database/manager
    数据库选择:http://127.0.0.1:8069/web/database/selector
    数据库指定:?db=database

    后台
      http://127.0.0.1:8069/web/
    前台
      http://127.0.0.1:8069/
    登录
      http://127.0.0.1:8069/web/login

    Odoo模块组成

    业务对象
      Python类,这些类会被Odoo框架自动持久化,持久化的方式决定于类的定义。
    数据文件
      包括视图、菜单、动作、工作流、权限、演示数据等,以XML或CSV文件定义。
    Web控制器
      处理Web浏览器的请求
    静态页面数据
      网站或界面使用的图片、CSS或JavaScript文件
    模块结构
      每个模块都是模块目录中的一个子目录, 可以通过 --addons-path 选项指定模块目录的路径

    odoo的设计模式 --> MVC模式
      M Model
      V View
      C Controller

    创建模块

    1 在odoo源码同层目录下创建目录: mkdir myaddons
    2 用odoo-bin的脚手架功能创建空的odoo模块
    ./odoo-bin scaffold todo myaddons

    odoo orm

    参考:参考手册

    自己的笔记跳转:  odoo10 orm操作

    视图

    自己的笔记跳转:  odoo10视图

    domains

    通过domain来过滤数据记录
    domain作用子一个model上: 用model.search(domain)
    Domain是定义模型子集的规则集合。domain表达式是由多个(field_name, operator, value)元组构成的列表或数组

    field_name -- 字段名或者用.号分隔的Many2one关系的字段如:'street' , 'partner_id.country'
    operator(str) -- 用于对字段值和给定值进行比较的运算符:
        =,!=,>,>=,<,<=,
        =?(值为false或none时返回true,否则与=效果一致)
        =like()将字段数据与value进行匹配,_代表匹配单个字符、%匹配0或多个字符
        like() 将字段数据与%value% 进行匹配,
        not like 不与%value%匹配
        ilike 忽略大小写的like函数
        not ilike 忽略大小写的not like
        =ilike 忽略大小写的=like
        in 与value的任意值相等,value须为值列表
        not in 与value的任意值都不相等
        child_of 是否由value派生而来
    value 对应值,必须与相应条件对应
        多个domain表达式可用运算符进行连接,运算符写在两个表达式之前。
            & 逻辑与 ,| 逻辑或,!逻辑非

    1 作用在关联字段上
      示例: 当为授课选择讲师时,只有instructor值为True的讲师会被显示出来。
      instructor_id = fields.Many2one('res.partner', string="Instructor", domain=[('instructor', '=', True)])

      注意: 声明为文字列表的domain会在服务端进行计算,右侧不可以是动态的字段; 而声明为字符串的domain是在客户端进行计算的,右侧可以是动态的字段

    2 作用在客户端上
      当在客户端界面选择记录集时,domain参数可以添加到关联字段上,以限制只显示有效的关联字段。
      <field name="instructor_id" domain="[('instructor', '=', True)]"/>

    计算字段

    odoo中提供一种每次引用字段, 通过方法动态计算的方式来获取字段值的方法

    1 创建计算字段
      - 创建一个字段
      - 将其属性compute设置为(计算)方法名称

    2 计算方法
      # ORM使用depends()装饰器来指定计算方法的依赖性。当某些依赖关系被修改后,ORM层通过给定的依赖关系来触发字段的重新计算。

      @api.multi
      @api.depends('value')
      def _compute_name(self):
        for record in self:
          record.name = "Record with value %s" % record.value

    默认值

    字段加上属性 default

      - 可以是一个值
      - 有返回值的匿名函数

    对象self.env提供对请求参数和其他有用的东西的访问

    self.env.cr 或者 self._cr            是数据库游标对象,通常用于查询数据库
    self.env.uid或者self._uid            是当前用户的数据库ID
    self.env.user                        是当前用户记录
    self.env.ref(xml_id)                返回XML ID对应的记录
    self.env[model_name]                返回给定模型的实例

    Odoo 有内置规则:active字段值为False时记录不可见

    onchange

    为客户端接口提供了一种方法, 只要用户填写了字段中的值, 就可以实时更新form表单, 而无需向数据库保存任何内容

    示例

    @api.onchange('amount', 'unit_price')        # onchange()的参数指定了在那个字段改变时,触发方法
    def _onchange_price(self):
        # 业务逻辑
        if flag:
            return {    # 可以返回一个错误信息
                'warning': {
                    'title': "Something bad happened",
                    'message': "It was very bad indeed",
                }
            }

    模型约束

    python代码级别约束

    在记录集上调用这个方法。装饰器参数指定了约束涉及的字段,当涉及的字段中任一发生改变时触发方法执行。如果不满足约束条件,该方法将引发异常:

    示例

    from odoo.exceptions import ValidationError
    
    @api.constrains('age')
    def _check_something(self):
        for record in self:
            if record.age > 20:
                raise ValidationError("Your record is too old: %s" % record.age)
        # all records passed the test, don't return anything

    sql数据库级别约束

    SQL约束通过模型属性_sql_constraints进行定义。

    它是一个三元素的元组的列表(name, sql_definition, message)

      - name 是SQL约束名称,
      - sql_definition 是约束规则,
      - message 是违反约束规则时的警告信息。

    示例

    _sql_constraints = [
        ('name_description_check',
         'CHECK(name != description)',
         "The title of the course should not be the description"),
    
        ('name_unique',
         'UNIQUE(name)',
         "The course title must be unique"),
    ]

    工作流

    工作流是与动态业务对象相关联的模型。工作流也用于跟踪动态(随时间)演进的进程。

    下面是工作流的两种实现方式

    1 伪工作流

    button标签的type='object'

    给模型添加一个字段state, 用于定义一个工作流程

    按钮 --> 模型的方法

    2 真工作流

    button标签的type='workflow'

    与模型相关的工作流仅在创建模型记录时被创建。因此,在工作流定义之前创建的授课实例是没有与之对应的工作流实例的。

    工作流的构成

    工作流

    # 有点类似一个【model的工作流模板】, 之后此model的工作流实例根据这个模板生成

    xml示例代码:

    <record model="workflow" id="wkf_session">
        <field name="name">OpenAcademy sessions workflow</field>
        <field name="osv">openacademy.session</field>
        <field name="on_create">True</field>
    </record>

    活动(节点)

    # 活动定义了应在Odoo服务器内完成的工作          例如更改某些记录的状态或发送电子邮件。

    不同的调用方式:

    <field name="kind">function</field>        # python代码     
    <field name="kind">dummy</field>           # 服务器的code
                                               # 还有 Subflow 和 Stop all,可以参考官方文档

    xml示例代码:

    <record model="workflow.activity" id="draft">
        <field name="name">Draft</field>
        <field name="wkf_id" ref="wkf_session"/>
        <field name="flow_start" eval="True"/>        # 标示了活动的开始节点
        <field name="kind">function</field>
        <field name="action">action_draft()</field>
    </record>

    转换

    # 控制工作流如何从活动到活动。

    xml示例代码:

    <record model="workflow.transition" id="session_draft_to_confirmed">
        <field name="act_from" ref="draft"/>
        <field name="act_to" ref="confirmed"/>
        <field name="signal">confirm</field>        # 【信号】: 通过button触发, button会根据name去找到相应的signal
    </record>

    实例

    # 创建一个recoed时, 会根据工作流模板, 生成工作流实例

    有点类似python面向对象的实例化

    条件

    当条件被满足时, 自动状态迁移, 有点类似 (条件+onchange)

    自动化的工作流: 设置一个condition

    xml示例代码:

    <record model="workflow.transition" id="session_auto_confirm_half_filled">
        <field name="act_from" ref="draft"/>
        <field name="act_to" ref="confirmed"/>
        <field name="condition">taken_seats > 50</field>
    </record>

    向导

    model --> ir.actions.act_window

    在odoo中通过使用向导创建一个表单与用户进行交互, 向导的model使用TransientModel定义

    运行wizard: 可以通过ir.actions.act_window模型表里的记录启动, 可以从menu里或者某个button触发;

          另外一种方式, 在form view上方的下拉按钮组(context action)中调用, 设置好src_model关联对应的model

    1 向导视图中:

    src_model     指向上下文的模型
    res_model     指向向导的模型
    
    target="new"        将弹出一个新窗口打开向导
    special="calcel"    关闭向导窗口而不保存

    2 向导模型中

    self._context        获取当前对象的模型的上下文

    注意: 向导记录不是永久性的, 会在一段时间后自动从数据库中删除. 这就是为什么他们被称为"瞬态"

    odoo报表

    报表构成

    1 在ir.actions.report.xml中定义报表记录, 使用<report>设置报表的各种基本参数

    id                 外部标示
    name            助记符/描述符
    model            报告涉及的模型
    report_type        qweb-pdf/qweb-html
    report_name        打印出来的名字
    groups            允许哪些组可以查看/使用报表
    attachment_use    设成True, 报表将使用附件表达式生成的名称存为记录的附件
    attachment        表达式
    paperformat        纸质格式的外部ID, 默认为公司的纸质格式

    2 Qweb view定义报表样式

    docs是从context发送过来的变量(上下文), 代表报表内容记录, 
    user代表打印此报表的人
    
    - external_layout        将在报表上添加默认页眉和页脚
    - PDF的body将会包含在<div class="page"> 
    - <template>的id必须是<report>里指定的name
    - <template>里可以使用的变量
        docs             记录当前报表
        doc_ids         docs 记录的id列表
        doc_model         模型为 docs 记录
        time             引用Python标准库的 time
        user             res.user 记录用户打印报表
        res_company     记录当前 user 的公司

    Qweb常用指令

    1 数据输出

    t-esc = 'value'            会做html转义, 有xss攻击的危险
    t-raw                      不转义

    2 条件

    t-if
    t-elif
    t-else

    3 循环

    t-foreach t-as
    t-esc # 设置: t-set = '...' t-value = ''

    4 属性

    计算属性: t-attr
    有3中不同的形式:

    1 t-attr-$name
    2 t-attf-$name
    3 t-att-mapping
      t-att-pair

    5 设置变量

    通过set指令完成

    两种方式

    1 t-value = '2+1'        # 可以是表达式
    2 如果没有t-value, 则节点的body将设置为变量的值

    6 调用子模版

    使用t-call调用其他模版

    神奇的0变量

    主模版:
        <div>
            This template was called with content:
            <t t-raw="0"/>        # 将会渲染为子的内容, 相当于为子的body预留位置
        </div>
    
    调用子模版:
        <t t-call="other-template">
            <em>content</em>
        </t>
        
    将会渲染成:
        <div>
            This template was called with content:
            <em>content</em>
        </div>

    动作

    参考 odoo10动作

    1 窗口动作

    --->  ir.actions.act_window

    res_model:要打开的视图(窗口)关联的数据模型
    view_type:视图类型,默认值为 form,一般情况下我们取默认值就可以了
    view_mode:允许打开的视图类型,以逗号分隔,默认值为 tree,form
    target:打开的窗口类型,常用的有 current(当前窗口打开)和 new (弹窗打开)这两种,默认为 current
    
    还有一些非必填的字段在某些时候我们是会用上的,这里也分列出来:
    view_ids:关联的视图对象 id,需注意区分和 view_id 的区别
    view_id:关联的视图的 id, 例如在不同时候需要打开同一个数据模型不同的表单视图,就可以通过这个字段指定要打开的视图的 id
    res_id:仅在视图类型为 form 时有效,表示打开该 id 对应的记录的表单视图,如未指定则打开新建页面
    context:传递到上下文中的数据,一个字典
    domain:过滤规则,对视图中的记录进行过滤
    limit:列表中每页显示的记录数量,默认为 80
    search_view_id:指定搜索视图,不指定则按默认规则加载
    multi:如果设置为 True 且动作绑定了模型(src_model)的话,该动作按钮会只出现在所绑定模型列表视图的「动作」下拉列表中(在搜索视图左侧)
    views:由 (view_id, view_type) 这样的元组对组成的列表,view_id 为指定视图的 id 或是 False(按默认值取出对应视图),view_type 表示视图类型

    2 服务器动作

    --->  ir.actions.server

    model_id:当前的动作是在哪个模型上运行的
    binding_model_id:绑定的模型,当前动作将会出现在绑定的模型的视图中
    state:服务器动作的类型,总共有 4 种可选的类型,分别是 code(执行 Python 代码),object_create(创建一条新记录),object_write(更新记录),multi(执行多个动作)
    code:对应 state 的类型 code,为当前动作运行时所要执行的 Python 代码
    
    我们定义的所有模型都会在 ir.model.data 对应的表中存在相应的记录
    
    接下来我们再看到字段 code 里面的内容,在这里面我们有一些变量是可以直接使用的:
    env:Odoo 的运行环境
    model:动作触发时对应的 Odoo 模型实例
    record:动作触发时对应的单个记录(如在表单视图中运行对应当前表单所指向的记录),可能是空的
    records:动作触发时对应的记录集(如在列表视图中勾选多条记录触发,记录集指向这些选中的记录),可能是空的
    Python 库:time, datetime, dateutil, timezone 时间相关的 Python 库
    log:用来记录日志信息
    Warning:通过 raise Warning('xxxxx') 抛出警告信息

    3 URL动作

    --->  ir.actions.act_url

    target:有两个可选值,分别是新窗口(new)打开链接,相当于 <a target='_blank' />,以及当前窗口(self)打开,相当于 <a target='_self' />
    url:要打开的目标页面的链接,可以是外部页面也可以是同域下的内部页面

    4 客户端动作

    触发一个完全右客户端(浏览器)执行的动作

    5 报表动作

    安全与权限

    参考 思否文档参考

    1 基于组对表的访问权限 --> CSV文件
    2 基于组对表中数据行的访问权限 --> XML文件
    3 字段级别     // contraint     # 通过contraint可以做到字段级别

    1 用户组的权限

    模块分类: ir.module.category
    用户组: res.groups

    a 定义用户组

    两个系统自带的用户组:

    base.group_user    基础用户组
    base.user_root    管理员账号

    用户组里每个字段所代表的含义:

    category_id:该用户组所属的模块分类    # <field name="category_id" ref="todo.module_category_todo"/>
    implied_ids:在当前用户组下的用户,同时加入该(字段所指定的)用户组中    
    users:该字段所指定的用户默认被加入到当前用户组中    # 将会默认获得此组权限的用户

    b 用户组的权限

    (先根据上一步创建用户组)

    用户组的权限定义以.csv文件存储的
    默认的权限记录文件: security/ir.model.access.csv
    里面有8个字段, 分别代表的含义如下;

    id:这条权限记录的 id,可以类比为 xml_id    # 类似xml的外部标识
    name:权限记录的名称
    model_id:id:要配置权限的模型的外部 ID (以 model_ 开头)
    group_id:id:应用此条权限配置的用户组的 id,若为空则默认对所有用户组生效        # 上一步创的用户组id
    perm_read:读取记录的权限,1 为拥有该权限,0 为不分配该权限
    perm_write:编辑更新记录的权限,取值同上
    perm_create:创建新记录的权限,取值同上
    perm_unlink:删除记录的权限,取值同上

    示例

    id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
    access_app02_contract,app02.contract,model_app02_contract,,1,1,1,0

    2 记录集权限

    (俗名: 规则)

    模型: ir.rule

    model_id:要应用该规则的模型的外部 ID # 模型的外部标识ID --> model_**_**
    domain_force:过滤条件,符合该条件的记录都将按照所定义权限进行检查,其中变量 user 表示当前用户的实例对象,可以直接使用
    groups:应用该规则的用户组,如果不指定则默认对全部用户应用该规则

    菜单隐藏

    只需要在对应的菜单项上添加一个groups属性即可,  里面的值可以是逗号分隔的多个用户组的外部ID

  • 相关阅读:
    es5预览本地文件、es6练习代码演示案例
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 836 矩形重叠(暴力)
    Subversion under Linux [Reprint]
    Subversion how[Reprint]
  • 原文地址:https://www.cnblogs.com/sunch/p/10553664.html
Copyright © 2011-2022 走看看