第六章 搜索

Odoo中最常用的操作一就是搜索, 与我们常见的管理系统不同的是Odoo的搜索是可以由用户自定义的, 具体地说, 就是Odoo的搜索系统提供了本页面全部支持搜索的字段列表和与之配套的操作列表, 用户根据自己的需求,搭积木式的方式组合出满足自己的搜索条件,然后确认,生成搜索的结果.

主要的实现部件就是页面右上角的搜索框, 搜索框的逻辑包括过滤、分组,基本的操作可以通过XML文件配置出来,有些比较高级的搜索需要通过代码的方式实现。

基本搜索

默认情况下,搜索框只有一个搜索对象的name字段的功能:

如果想要搜索其他字段,就需要在filter中自行选择要搜索的字段和需要的操作符,进行过滤搜索:

可供选择的操作符包括如下几种:

  • 包含
  • 不包含
  • 等于
  • 不等于
  • 已设置
  • 未设置

这样基本可以满足用户的需求。

这里可选字段包括了本对象中所有可存储的字段,也就是在数据库中可搜索的字段,对于compute类型的字段来说,不可以搜索,也就不会出现在备选字段中。

用户可以点击favorites进行收藏,将当前的筛选条件进行保存,以供下次搜索使用。

自定义搜索

基本搜索满足了用户的基本搜索需求,但是不够简洁快速,如果想要更快捷的方式,就需要自定义搜索条件了。自定义搜索条件,基本可以通过配置XML文件实现,下面就详细介绍一下这几种搜索方式。

Filter

顾名思义,Filter就是过滤,具体的定义规则就是在XML文件中定义一个search视图:

<record id="book_store_search_view" model="ir.ui.view">
      <field name="name">图书搜索</field>
      <field name="model">book_store.book</field>
      <field name="arch" type="xml">
        <search string="图书搜索">
          <field name="author"/>
          <field name="date"/>
          <field name="price"/>
          <separator/>
          <filter name="liu_book" string="大刘小说" domain="[('author','=','刘慈欣')]" />
          <separator/>
          <group expand="0" string="Group By">
            <filter name="author" string="按作者分组" domain="[]" context="{'group_by':'author'}"/>
          </group>
        </search>
      </field>
    </record>

search结点中的三种标签:

  • field: 按字段搜索,即你输入值以后,下拉进行筛选:

  • filter: 按照预定的domain进行过滤:

  • group: 根据字段进行分组: 分组的做法是在context属性的中传入'group_by'的字段值。

计算字段的搜索

在Odoo中还有一类字段,是不存储在数据库中的,而是通过计算的方式在需要显示的时候计算出来的值。这类字段通常会使用compute属性,compute对应的是一个方法,这个方法在字段被显示和调用时调用。

沿用以前的模块,我们给book模型添加一个书龄的属性,该属性是由计算出来的:

age = fields.Integer('书龄', compute="_get_book_age", search="_search_ages")

@api.depends('date')
def _get_book_age(self):
    self.age = (datetime.now().date() - self.date).days

在form页面中会显示出该书的书龄:

你在filter工具中是看不到该字段的,那么我们如何对书龄进行搜索呢?

这里需要用到我们前面说过的一个字段的一个属性,search,search是用来重载字段被搜索时的方法的。搜索书龄,我们可以这么写:

@api.model
def _search_ages(self, operator, operand):
    """search方法"""
    if operator not in ('>', '>=', '<', '<=', '='):
        return []
    if type(operand) not in (float, int):
        return []
    start_date = datetime.now().date() - timedelta(days=operand)
    ops = {
        ">": "<",
        ">=": "<=",
        "<": ">",
        "<=": ">=",
        "=": "="
    }
    return [('date', ops[operator], start_date)]

search方法接收两个参数,一个操作符,一个是操作数,操作符根据字段的类型不同而不同,我们这里是integer类型,所对应的操作符就是大于小于和等于等操作符。search方法的返回值是一个domain对象,也就是有元组组成的列表。odoo会根据domain对记录进行过滤,并显示结果,最后的效果图如下:

results matching ""

    No results matching ""