关于 frappe-api-development
面向 Frappe 开发者的 API 开发指南,介绍 REST、RPC 和 Webhook 模式,以及认证、权限和输入校验。适用于构建集成接口或向前端开放业务逻辑。
主要功能
- 01选择 REST、RPC 或 Webhook 模式
- 02创建自定义 RPC 端点
- 03配置令牌、会话等认证方式
- 04检查权限并校验输入
- 05为耗时操作安排后台任务
适用场景
- 01为 DocType 提供 CRUD 接口
- 02向前端开放自定义业务操作
- 03接收外部系统回调
- 04运行导出等耗时任务并查询状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ lubusin/ frappe-skills --skill frappe-api-development安装后在 Claude Code 中输入/frappe-api-development确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/authentication.mdoauth.mdpermissions.mdpython-api.mdrate-limiting.mdrest-api.mdserver-scripts.mdwebhooks.md详细介绍
Frappe API 开发
使用 Frappe 的 REST 和 RPC 模式构建安全、设计完善的 API。
使用场景
- 创建自定义 RPC 端点(
@frappe.whitelist) - 构建 REST API 集成
- 为外部系统实现 Webhook
- 设置 API 身份验证(令牌、OAuth)
- 向前端开放业务逻辑
所需输入
- API 用途(CRUD、操作、集成)
- 身份验证要求(公开、用户、API 密钥)
- 各端点的权限要求
- 请求和响应格式预期
流程
0) 选择 API 模式
| 需求 | 模式 |
|---|---|
| DocType CRUD | 使用内置 REST API |
| 自定义操作 | 使用 @frappe.whitelist 的 RPC |
| 外部回调 | Webhook DocType |
| 批量操作 | 后台作业 + 状态端点 |
1) 内置 REST API(DocType CRUD)
Frappe 会为所有 DocType 自动提供 REST 端点:
# Create
POST /api/resource/Customer
{"customer_name": "Acme Corp"}
# Read
GET /api/resource/Customer/CUST-001
# Update
PUT /api/resource/Customer/CUST-001
{"customer_name": "Acme Corporation"}
# Delete
DELETE /api/resource/Customer/CUST-001
# List with filters
GET /api/resource/Customer?filters=[["status","=","Active"]]
2) 自定义 RPC 端点
在应用中创建白名单方法:
# my_app/api.py
import frappe
@frappe.whitelist()
def process_order(order_id, action):
"""Process an order with the given action."""
# Always verify permissions
doc = frappe.get_doc("Sales Order", order_id)
if not frappe.has_permission("Sales Order", "write", doc):
frappe.throw("Not permitted", frappe.PermissionError)
# Business logic
if action == "approve":
doc.status = "Approved"
doc.save()
return {"status": "success", "order": doc.name}
@frappe.whitelist(allow_guest=True)
def public_endpoint():
"""Public endpoint - no auth required."""
return {"message": "Hello, World!"}
通过以下方式调用:
POST /api/method/my_app.api.process_order
{"order_id": "SO-001", "action": "approve"}
3) 实现身份验证
API 密钥 + 密钥(推荐用于集成):
# Header format
Authorization: token api_key:api_secret
Bearer 令牌:
Authorization: Bearer <token>
会话(适用于已登录用户): 通过 Cookie 自动完成。
4) 权限检查
务必在 RPC 方法中检查权限:
@frappe.whitelist()
def sensitive_action(docname):
doc = frappe.get_doc("My DocType", docname)
# Check document-level permission
if not frappe.has_permission("My DocType", "write", doc):
frappe.throw("Not permitted", frappe.PermissionError)
# Check role-based permission
if "Manager" not in frappe.get_roles():
frappe.throw("Manager role required")
# Proceed with action
...
5) 输入验证
@frappe.whitelist()
def create_item(name, qty, price):
# Validate required fields
if not name:
frappe.throw("Name is required")
# Validate types
qty = frappe.utils.cint(qty)
price = frappe.utils.flt(price)
# Validate ranges
if qty <= 0:
frappe.throw("Quantity must be positive")
# Proceed
...
6) 响应格式
成功响应:
return {
"status": "success",
"data": {...}
}
错误处理:
# User-facing error
frappe.throw("Validation failed", title="Error")
# Permission error
frappe.throw("Not allowed", frappe.PermissionError)
# Standard exceptions become {"exc_type": "...", "exc": "..."}
7) 长时间操作的后台作业
@frappe.whitelist()
def start_export(filters):
job = frappe.enqueue(
"my_app.jobs.run_export",
filters=filters,
queue="long",
timeout=600
)
return {"job_id": job.id}
@frappe.whitelist()
def check_job_status(job_id):
from frappe.utils.background_jobs import get_job
job = get_job(job_id)
return {"status": job.get_status()}
验证
- 端点能正确响应有效请求
- 未经授权的访问会返回权限错误
- 输入验证会拒绝无效数据
- 错误响应格式清晰且有帮助
- 运行:
bench --site <site> console→ 手动测试端点
故障模式 / 调试
- 找不到方法:检查 URL 中的模块路径是否与 Python 路径匹配
- 权限被拒绝:确认
@frappe.whitelist()装饰器和用户权限设置正确 - CSRF 错误:为 API 调用使用正确的身份验证标头
- 500 错误:检查错误日志:
bench --site <site> show-log
升级处理
- OAuth 集成请参阅 references/oauth.md
- Webhook 模式请参阅 references/webhooks.md
- 速率限制请参阅 references/rate-limiting.md
参考资料
- references/rest-api.md - REST API 详情
- references/authentication.md - 身份验证模式
- references/permissions.md - 权限系统
- references/webhooks.md - 出站 Webhook
防护措施
- 始终验证输入:切勿信任客户端数据;在服务端验证类型、长度和格式
- 使用权限回调:在白名单方法中显式检查
frappe.has_permission() - 清理用户输入:对 SQL 使用
frappe.db.escape(),避免使用eval()和动态代码执行 - 处理速率限制:为公开 API 实施速率限制,防止滥用
- 返回结构化错误:使用
frappe.throw()并设置恰当的 HTTP 状态码
常见错误
| 错误 | 失败原因 | 修复方法 |
|---|---|---|
缺少 @frappe.whitelist() | 方法返回“找不到方法”错误 | 添加装饰器,通过 API 暴露方法 |
| 使用 GET 执行修改操作 | 违反 REST 约定,并引发 CSRF 问题 | 使用 POST/PUT/DELETE 修改数据 |
| 未处理错误 | 500 错误会暴露堆栈跟踪 | 使用 try/except 包裹,并调用 frappe.throw() |
| 暴露敏感数据 | 安全漏洞 | 过滤响应字段并检查权限 |
缺少 allow_guest=True | 公开端点返回 403 | 添加 @frappe.whitelist(allow_guest=True),允许未经身份验证的访问 |
| 查询中存在 SQL 注入 | 数据库遭到入侵 | 使用 Query Builder 或 frappe.db.escape() |
评论
支持 Markdown