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

  • 相关阅读:
    SLAB
    /proc/vmstat 详解
    swap空间可以有效缓解内存压力
    内存问题排查手段及相关文件介绍
    buddyinfo 内存碎片数据采集
    取得Linux系统的各种统计信息
    HTML的常用总结
    采用jquery同django实现ajax通信
    Django的quarySet
    Django-MySQL数据库使用01
  • 原文地址:https://www.cnblogs.com/sunch/p/10553664.html
Copyright © 2011-2022 走看看