「Odoo基础教程系列」——从 Todo 应用开始之搜索视图
在前面教程中,我们使用了两种类型的视图——TreeView 和 FormView. 今天我们将学习使用另一种类型的视图——SearchView, 搜索视图。
搜索字段
通过之前的实践,我们应该已经知道 Odoo 会为我们的模型定义默认的 TreeView 和 FormView 了吧,那对于我们今天要说的主角 SearchView 其实也是一样的,我们打开任意一个列表视图,都可以在列表的右上方看到有搜索框,除了能在搜索框里输入文字进行检索外,点一下搜索框右侧的放大镜还能展开更多的搜索功能,包括过滤器(
Filters
),分组(Group By
)以及收藏(Favorites
),其中最常用的就是过滤器了,我们稍候将会讲到。默认的搜索视图只会对模型的
name
字段(或 _rec_name
指定的字段)进行检索,例如在我们的待办事项列表中搜索,会看到搜索框下方自动出现了搜索项,这里的「描述」也就是我们的待办事项模型 todo.task
的 name
字段了:![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F1e815405-0f19-472d-9c1f-0c1ef26f71d3%2FUntitled.png?table=block&id=23ef36dd-980b-4e31-bd85-c4647f83a511&cache=v2)
那我们如果想让「分类」也能用于待办事项的搜索,该怎么做呢?我们接下来就打开视图文件,先定义好搜索视图的基本结构:
<!-- views.xml --> <record id="todo_task_view_filter" model="ir.ui.view"> <field name="name">todo.task.view_filter</field> <field name="model">todo.task</field> <field name="arch" type="xml"> <search string="Todo"> ... </search> </field> </record>
搜索视图和列表视图以及表单视图一样,都有相似的结构,唯一不同的就是在
arch
内的部分。接下来我们要在 <search />
中加上我们想要搜索的字段:<search string="Todo"> <field name="name"/> <field name="category_id"/> </search>
超简单有没有!只需要把想要被用于搜索的字段放到
<search />
内就可以了,这里需要注意的是,我们自己定义了搜索视图,相当于覆盖掉了默认的视图,所以我们还需要将字段 name
也加入到里面,不然我们就没办法根据待办事项的描述进行搜索啦。升级一下模块,在输入框随便输入搜索内容看看发生了什么变化:
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fc3c9142c-2022-4e77-b201-8632fabb7435%2FUntitled.png?table=block&id=efbee47f-0dd4-43c7-91ed-ff4bc6b23f0b&cache=v2)
还记得我们之前创建过「工作」这个分类吗,在下面列出的「分类」的搜索结果中,点击小三角符号,就会打开匹配到的相关结果。
过滤器
我们再来看看 Odoo 的搜索视图自带的过滤器,点开之后我们只看到一个添加自定义过滤器的选项,再点一下看看,出现了一些选项:
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ff31b152f-a27e-443d-8fe3-2e3ccbe86942%2FUntitled.png?table=block&id=b92a5c9d-d465-474e-92e2-03906d741ad2&cache=v2)
我们试试随意添加一些规则,然后点击应用,看看会有什么发生(我分别选择了「紧急程度」「is」「普通」):
![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F8fee189b-e320-465a-ad9d-ff76e9ba2299%2FUntitled.png?table=block&id=7e80d41b-1ed0-4ae6-b27d-e1adc22df30f&cache=v2)
我们可以看到在搜索框中,应用了这个过滤器,并且这个过滤器被添加到了过滤器的选项中,我们还可以再添加几个过滤器试试看。
通过以上的操作,我们不难看出,这里的过滤器其实就是一个个过滤规则,而且我们可以同时应用多个不同的规则。如果我们有大量的数据,而我们想要快速筛选出特定的数据的话,就可以使用过滤器达到这个目的。
如果我们切换到其他菜单或者刷新页面,就会发现之前应用的过滤器,又消失了,如果我们在某些数据上需要高频次进行过滤操作的话,每次都要手动添加过滤规则的话,就显得十分不方便了,所以我们来看看怎么在搜索视图中定义过滤器吧:
<search string="Todo"> <field name="name"/> <field name="category_id"/> <separator/> <filter string="未完成" name="undone" domain="[('is_done', '=', False)]"/> <filter string="已完成" name="done" domain="[('is_done', '=', True)]"/> <separator/> <filter string="待办" name="todo" domain="[('priority', '=', 'todo')]"/> <filter string="普通" name="normal" domain="[('priority', '=', 'normal')]"/> <filter string="紧急" name="urgency" domain="[('priority', '=', 'urgency')]"/> </search>
我们在
<search />
里添加了五个过滤器 <filter />
,其中 string
是显示的名称,name
是数据库中存储的名字,我们可以通过它来获取到对应的过滤器,最关键的一个属性就是 domain
了。在 Odoo 中的各种过滤都是通过domain
来实现的,它是一个由逻辑前缀和表达式元组组成的列表,关于 domain
的更多细节,这里先不展开来说,后面应该会专门写一篇来说说它。我们以「未完成」这个过滤器的 domain 为例,先不管条件是什么,先写下一个空的列表
[]
,这里要记住了,只要是用到 domain 的地方,都先写下一对中括号 []
,因为刚接触常常会因为少写了括号而导致程序出现错误。然后我们先不考虑逻辑前缀的事情,我们这里也暂时没有用到,所以不要让这个名词困扰到了。在刚刚写下的空列表中,添加一对圆括号
()
,也就是一个元组,最基本的结构已经有了,现在我们来写表达式。我们用来标记一个待办事项是否完成,用的是字段 is_done
,如果它的值为 False
则表示这个待办事项未完成,反之则表示已完成,根据这个规则,我们可以在元组中添加我们的表达式了,先写下字段名 'is_done'
(注意这里是字符串),然后写下表达式的操作符 '='
(这里也是一个字符串),最后写下未完成对应的值 False
(这里是一个布尔值,非字符串)。怎么样,是不是很简单呢,可能有同学要问了,为什么这里是用等于号
=
而不是 ==
呢?这里就需要大家注意并且习惯了,不同于我们平时写代码判断相等时会用 ==
双等号,在 domain 的表达式中判断相等是使用的 =
单个等号,千万记住啦!其他的过滤器我们也能使用同样的方式写出来,大家再好好理解一下吧。我们再来看到上面出现的
<separator />
这个标签,它有两个作用,一个是将搜索字段和过滤器之间进行分组隔离,另一个作用是以逻辑与(Python 中的 and
)对搜索字段和过滤器进行连接,说再多不如实践来得清楚,我们先升级一下代码,然后刷新页面看看实际的效果吧:![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F8eaec1fb-617a-49c2-9e14-b87b298baada%2FUntitled.png?table=block&id=c1d7a5b7-4b02-482e-840a-d2131f4ba5c4&cache=v2)
心细的你一定发现了,是否完成的过滤器和紧急程度的过滤器被一条分割线分隔开了,从上面的代码中我们可以看到这根分割线正是
<separator />
这个标签在界面上显示的效果。我们如果同时勾选同一组内的过滤器,可以发现搜索框内的过滤器被 or
连接起来了,这表明了同一组内的过滤器会使用逻辑或(Python 中的 or
)进行连接,而如果同时选中两个不同组的过滤器,搜索框内的过滤器标签则是分开的,也就是我们前面说的,被用逻辑与连接起来了。试试看在搜索框中输入内容并搜索,然后加上过滤器组合看看效果吧,有没有发现什么呢?再看看搜索视图的代码,在
<field />
和 <filter />
之间还有一个 <separator />
呢。分组
使用字段搜索和过滤器,已经可以满足大部分数据的搜索需求了,有时候我们除了需要按规则过滤出所需的数据外,还会需要对数据进行分组查看,这种时候就可以用上分组(
group by
)功能了。和过滤器一样,分组功能我们同样可以自己添加自定义的分组,但是要比过滤器简单得多,只需要选择一个字段然后应用即可。
我们来看看在搜索视图中如何定义分组项:
<search string="Todo"> ... <filter string="紧急" name="urgency" domain="[('priority', '=', 'urgency')]"/> <group expand="0" string="分组"> <filter string="分类" domain="[]" context="{'group_by':'category_id'}"/> <filter string="紧急程度" domain="[]" context="{'group_by':'priority'}"/> </group> </search>
我们添加了一个
<group />
标签,并且在里面添加了两个 <filter />
,眼尖的你一定发现了,这里和过滤器长得一模一样,只是多了一个 context
属性,是的没有错,分组的关键也就在这个 context
属性里,里面是一个字典,对应的键值对表示按指定字段进行分组。另外我们再看到这里留空的
domain
,大家可以尝试在里面添加一些表达式,看看会有什么效果,这里我就不细说了,快升级模块然后去页面中刷新看看效果吧:![notion image](https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F5f7bdb3c-1aa3-45d3-9bd5-64fe08795f34%2FUntitled.png?table=block&id=8c81c286-f35c-4041-91be-14bc446165bd&cache=v2)
我们可以看到数据按照我们所选的分组项进行了分组,并且默认是折叠起来的,点击展开之后我们可以看到对应分组下的数据,默认折叠这个行为是由
<group />
标签的 expand
属性决定的,如果设置为 1 的话就会是默认展开。大家可以试试看同时应用多个分组,或者将分组和过滤器组合使用,仔细观察和思考产生的结果。
瞎说几句
以上就是这次教程的内容啦,SearchView 中还有一个收藏功能我们没有讲到,这个功能我们目前或者很长的一段时间内都不会用到,所以也不打算在之后的教程中讲解,如果感兴趣的话可以自己尝试着去使用,安装一些官方的模块,又或者看看源代码,去学习相关的知识。
还是老规矩,教程中的代码会更新在
GitHub
仓库「Odoo-Tutorial-Demo」中。 本文采用 CC BY-NC-ND 4.0 许可协议。转载或引用时请遵守协议内容!