erpnext-syntax-serverscripts

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ERPNext Server Scripts Syntax

ERPNext Server Scripts 语法参考

Server Scripts are Python scripts that run within Frappe's secure sandbox environment. They are managed via Setup → Server Script in the ERPNext UI.
Server Scripts 是运行在 Frappe 安全沙箱环境中的 Python 脚本。可通过 ERPNext 界面中的 设置 → 服务器脚本 进行管理。

CRITICAL: Sandbox Limitations

重要提示:沙箱限制

┌─────────────────────────────────────────────────────────────────────┐
│ ⚠️  NO IMPORTS ALLOWED                                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ The sandbox blocks ALL import statements:                          │
│   import json        → ImportError: __import__ not found           │
│   from datetime import date  → ImportError                         │
│                                                                     │
│ SOLUTION: Use Frappe's pre-loaded namespace:                       │
│   frappe.utils.nowdate()     not: from frappe.utils import nowdate │
│   frappe.parse_json(data)    not: import json; json.loads(data)    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ ⚠️  NO IMPORTS ALLOWED                                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│ 沙箱会阻止所有导入语句:                          │
│   import json        → ImportError: __import__ not found           │
│   from datetime import date  → ImportError                         │
│                                                                     │
│ 解决方案:使用 Frappe 预加载的命名空间:                       │
│   frappe.utils.nowdate()     而非: from frappe.utils import nowdate │
│   frappe.parse_json(data)    而非: import json; json.loads(data)    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Server Script Types

服务器脚本类型

TypeUsageTrigger
Document EventReact to document lifecycleSave, Submit, Cancel, etc.
APICustom REST endpointHTTP request to
/api/method/{name}
Scheduler EventScheduled tasksCron schedule
Permission QueryDynamic list filteringDocument list view
类型用途触发方式
文档事件响应文档生命周期保存、提交、取消等
API自定义 REST 端点HTTP 请求到
/api/method/{name}
调度器事件定时任务Cron 调度规则
权限查询动态列表过滤文档列表视图

Event Name Mapping (Document Event)

事件名称映射(文档事件)

IMPORTANT: The UI event names differ from the internal hook names:
UI Name (Server Script)Internal HookWhen
Before Insert
before_insert
Before new doc to DB
After Insert
after_insert
After new doc saved
Before Validate
before_validate
Before validation
Before Save
validate
Before save (new or update)
After Save
on_update
After successful save
Before Submit
before_submit
Before submit
After Submit
on_submit
After submit
Before Cancel
before_cancel
Before cancel
After Cancel
on_cancel
After cancel
Before Delete
on_trash
Before delete
After Delete
after_delete
After delete
重要提示:UI 中的事件名称与内部钩子名称不同:
UI 名称(服务器脚本)内部钩子触发时机
插入前
before_insert
新文档存入数据库前
插入后
after_insert
新文档保存后
验证前
before_validate
验证操作前
保存前
validate
保存前(新建或更新)
保存后
on_update
保存成功后
提交前
before_submit
提交操作前
提交后
on_submit
提交操作后
取消前
before_cancel
取消操作前
取消后
on_cancel
取消操作后
删除前
on_trash
删除操作前
删除后
after_delete
删除操作后

Quick Reference: Available API

快速参考:可用 API

Always available in sandbox

沙箱中始终可用

python
undefined
python
undefined

Document object (in Document Event scripts)

文档对象(文档事件脚本中)

doc # Current document doc.name # Document name doc.doctype # DocType name doc.fieldname # Field value doc.get("fieldname") # Safe field access doc.items # Child table (list)
doc # 当前文档 doc.name # 文档名称 doc.doctype # 文档类型名称 doc.fieldname # 字段值 doc.get("fieldname") # 安全字段访问 doc.items # 子表(列表)

Frappe namespace

Frappe 命名空间

frappe.db # Database operations frappe.get_doc() # Fetch document frappe.get_all() # Multiple documents frappe.throw() # Validation error frappe.msgprint() # User message frappe.log_error() # Error logging frappe.utils.* # Utility functions frappe.session.user # Current user frappe.form_dict # Request parameters (API) frappe.response # Response object (API)
undefined
frappe.db # 数据库操作 frappe.get_doc() # 获取文档 frappe.get_all() # 获取多个文档 frappe.throw() # 抛出验证错误 frappe.msgprint() # 用户提示消息 frappe.log_error() # 错误日志 frappe.utils.* # 工具函数 frappe.session.user # 当前用户 frappe.form_dict # 请求参数(API 脚本) frappe.response # 响应对象(API 脚本)
undefined

Decision Tree: Which Script Type?

决策树:选择哪种脚本类型?

What do you want to achieve?
├─► React to document save/submit/cancel?
│   └─► Document Event script
├─► Create REST API endpoint?
│   └─► API script
├─► Run task on schedule?
│   └─► Scheduler Event script
└─► Filter document list view per user/role?
    └─► Permission Query script
你想要实现什么功能?
├─► 响应文档的保存/提交/取消操作?
│   └─► 文档事件脚本
├─► 创建 REST API 端点?
│   └─► API 脚本
├─► 按计划运行任务?
│   └─► 调度器事件脚本
└─► 按用户/角色过滤文档列表视图?
    └─► 权限查询脚本

Basic Syntax per Type

各类型基本语法

Document Event

文档事件

python
undefined
python
undefined

Configuration:

配置:

Reference DocType: Sales Invoice

参考文档类型:销售发票

DocType Event: Before Save (= validate)

文档类型事件:保存前(= validate)

if doc.grand_total < 0: frappe.throw("Total cannot be negative")
if doc.grand_total > 10000: doc.requires_approval = 1
undefined
if doc.grand_total < 0: frappe.throw("总金额不能为负数")
if doc.grand_total > 10000: doc.requires_approval = 1
undefined

API

API

python
undefined
python
undefined

Configuration:

配置:

API Method: get_customer_info

API 方法:get_customer_info

Allow Guest: No

允许访客访问:否

Endpoint: /api/method/get_customer_info

端点:/api/method/get_customer_info

customer = frappe.form_dict.get("customer") if not customer: frappe.throw("Customer parameter required")
data = frappe.get_all( "Sales Order", filters={"customer": customer, "docstatus": 1}, fields=["name", "grand_total"], limit=10 ) frappe.response["message"] = data
undefined
customer = frappe.form_dict.get("customer") if not customer: frappe.throw("缺少客户参数")
data = frappe.get_all( "Sales Order", filters={"customer": customer, "docstatus": 1}, fields=["name", "grand_total"], limit=10 ) frappe.response["message"] = data
undefined

Scheduler Event

调度器事件

python
undefined
python
undefined

Configuration:

配置:

Event Frequency: Cron

事件频率:Cron

Cron Format: 0 9 * * * (daily at 9:00)

Cron 格式:0 9 * * *(每天 9:00 运行)

overdue = frappe.get_all( "Sales Invoice", filters={"status": "Unpaid", "due_date": ["<", frappe.utils.today()]}, fields=["name", "customer"] )
for inv in overdue: frappe.log_error(f"Overdue: {inv.name}", "Invoice Reminder")
frappe.db.commit()
undefined
overdue = frappe.get_all( "Sales Invoice", filters={"status": "Unpaid", "due_date": ["<", frappe.utils.today()]}, fields=["name", "customer"] )
for inv in overdue: frappe.log_error(f"逾期发票:{inv.name}", "发票提醒")
frappe.db.commit()
undefined

Permission Query

权限查询

python
undefined
python
undefined

Configuration:

配置:

Reference DocType: Sales Invoice

参考文档类型:销售发票

Output: conditions string for WHERE clause

输出:WHERE 子句的条件字符串

user_roles = frappe.get_roles(user)
if "System Manager" in user_roles: conditions = "" # Full access elif "Sales User" in user_roles: conditions = f"
tabSales Invoice
.owner = {frappe.db.escape(user)}" else: conditions = "1=0" # No access
undefined
user_roles = frappe.get_roles(user)
if "System Manager" in user_roles: conditions = "" # 完全访问权限 elif "Sales User" in user_roles: conditions = f"
tabSales Invoice
.owner = {frappe.db.escape(user)}" else: conditions = "1=0" # 无访问权限
undefined

References

参考资料

  • references/events.md - Complete event mapping and execution order
  • references/methods.md - All available frappe.* methods in sandbox
  • references/examples.md - 10+ working examples per script type
  • references/anti-patterns.md - Sandbox limitations and common mistakes
  • references/events.md - 完整的事件映射和执行顺序
  • references/methods.md - 沙箱中所有可用的 frappe.* 方法
  • references/examples.md - 每种脚本类型的 10+ 个可用示例
  • references/anti-patterns.md - 沙箱限制和常见错误

Version Information

版本信息

  • Frappe v14+: Server Scripts fully supported
  • Activation required:
    bench --site [site] set-config server_script_enabled true
  • Frappe v15: No significant syntax changes for Server Scripts
  • Frappe v14+:完全支持 Server Scripts
  • 需要激活
    bench --site [site] set-config server_script_enabled true
  • Frappe v15:Server Scripts 无重大语法变更