# 控制器

控制器是一个普通的Python类,它扩展自frappe.model.Document基类。这个基类是DocType的核心逻辑。它处理如何从数据库加载值,如何解析并将它们保存回数据库。

当您创建一个名为Person的DocType时,会创建一个名为person.py的Python文件,内容如下:

import frappe
from frappe.model.document import Document

class Person(Document):
    pass

1
2
3
4
5
6

类中所有字段都可作为属性使用。

# 控制器方法

您可以在控制器中添加自定义方法,并通过doc对象调用。例如,

# 控制器类
class Person(Document):
    def get_full_name(self):
        """返回人的全名"""
        return f"{self.first_name} {self.last_name}"

# 在代码中的某处
>>> doc = frappe.get_doc("Person", "000001")
>>> doc.get_full_name()
John Doe

1
2
3
4
5
6
7
8
9
10
11

# 控制器钩子

为了在文档的生命周期中添加自定义行为,我们有控制器钩子。

方法名称 描述 插入 保存 提交 取消 提交后更新
before_insert 文档准备插入前调用 X
before_naming 文档的name属性设置前调用 X
autoname 如果在控制器中定义,此方法用于设置文档的name属性 X
before_validate 验证前调用此钩子,用于自动设置缺失的值 X X X
validate 使用此方法抛出任何验证错误并阻止文档保存 X X X
before_save 文档保存前调用此方法 X X
before_submit 文档提交前调用此方法 X
before_cancel 文档取消前调用此方法 X
before_update_after_submit 当提交的文档字段更新时调用此方法 X
db_insert 此方法将文档插入数据库,除非您正在处理虚拟DocType,否则不要覆盖此方法 X
after_insert 文档插入数据库后调用 X
db_update 此方法更新数据库中的文档,除非您正在处理虚拟DocType,否则不要覆盖此方法 X X X X
on_update 当现有文档的值更新时调用 X X
on_submit 当文档提交时调用 X
on_cancel 当提交的文档被取消时调用 X
on_update_after_submit 提交的文档值更新时调用 X
on_change 当文档的值发生变化时调用。此方法在执行db_set时也会被调用,因此在这个方法中执行的操作应该是幂等的 X X X X X

除了典型动作的文档事件外,您还可以钩住其他动作。

方法名称 描述
before_rename 文档重命名前调用
after_rename 文档重命名后调用
on_trash 文档被删除时调用
after_delete 文档被删除后调用

要使用控制器钩子,只需定义一个具有该名称的类方法。例如

class Person(Document):
    def validate(self):
        if self.age <= 18:
            frappe.throw("Person's age must be at least 18")

    def after_insert(self):
        frappe.sendmail(recipients=[self.email], message="Thank you for registering!")

1
2
3
4
5
6
7
8

如果钩子不足以满足您的需求,您还可以覆盖预定义的文档方法以添加您自己的行为。例如要覆盖save()方法,

class Person(Document):
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs) # 调用基类保存方法
        do_something() # 例如:触发一个API调用或一个记录"用户X尝试更新这个特定记录"的旋转文件记录器

1
2
3
4
5

doc对象提供了许多默认方法。您可以在此处找到完整列表。

# 1. 创建文档

要创建一个新文档并将其保存到数据库,

doc = frappe.get_doc({
    'doctype': 'Person',
    'first_name': 'John',
    'last_name': 'Doe'
})
doc.insert()

doc.name # 000001

1
2
3
4
5
6
7
8
9

# 2. 加载文档

要从数据库中获取现有文档,

doc = frappe.get_doc('Person', '000001')

# doctype 字段
doc.first_name # John
doc.last_name # Doe

# 标准字段
doc.creation # datetime.datetime(2018, 9, 20, 12, 39, 34, 236801)
doc.owner # john.doe@frappeframework.com

1
2
3
4
5
6
7
8
9
10

# 文档

文档是DocType的一个实例。它通常映射数据库表中的一行。我们在代码中称之为doc

示例

假设我们有一个名为ToDo的DocType,包含以下字段:

  • description

  • status

  • priority

现在,如果我们想从数据库中查询一个文档,我们可以使用ORM。

>>> doc = frappe.get_doc("ToDo", "0000001")
<todo: 0000001="">

>>> doc.as_dict()
{'name': '0000001',
 'owner': 'Administrator',
 'creation': datetime.datetime(2022, 3, 28, 18, 20, 23, 275229),
 'modified': datetime.datetime(2022, 3, 28, 18, 20, 23, 275229),
 'modified_by': 'Administrator',
 'docstatus': 0,
 'idx': 0,
 'status': 'Open',
 'priority': 'Medium',
 'color': None,
 'date': None,
 'allocated_to': None,
 'description': 'Test',
 'reference_type': None,
 'reference_name': None,
 'role': None,
 'assigned_by': 'Administrator',
 'assigned_by_full_name': 'Administrator',
 'sender': None,
 'assignment_rule': None,
 'doctype': 'ToDo'}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

您可以获得descriptionstatuspriority的值,但您还会获得像creationownermodified_by这样的字段,这些字段是由框架在所有docs上默认添加的。

# 类型注释

从版本15开始引入。

Frappe支持在控制器文件中自动生成Python类型注释。这些注释可用于控制器文件内的自动完成、引用和类型检查。

class Person(Document):
    # 自动生成类型
    # 此代码是自动生成的。不要在此代码块中修改任何内容。

    from typing import TYPE_CHECKING

    if TYPE_CHECKING:
        from frappe.types import DF

        first_name: DF.Data
        last_name: DF.Data
        user: DF.Link
    pass

1
2
3
4
5
6
7
8
9
10
11
12
13
14

注意:在创建或更新doctypes时生成这些注释。如果您修改了代码块,它将在下次更新时被覆盖。

您可以通过在应用中添加以下钩子来配置自动导出。

# hooks.py

export_python_type_annotations = True
1
2
3

了解更多关于类型注释的信息:

  • https://docs.python.org/3/library/typing.html

  • VS Code用户可以安装Python扩展以获得更好的自动完成 - https://code.visualstudio.com/docs/languages/python

  • 大多数其他编辑器都有等效的插件系统,使用LSP。

最后更新时间: 9/27/2024, 3:24:28 PM