mcpField
F
frappe-api-development

frappe-api-development

github.com/lubusin开发69248 次安装12 周前更新
代码仓库

关于 frappe-api-development

面向 Frappe 开发者的 API 开发指南,介绍 REST、RPC 和 Webhook 模式,以及认证、权限和输入校验。适用于构建集成接口或向前端开放业务逻辑。

主要功能

  1. 01选择 REST、RPC 或 Webhook 模式
  2. 02创建自定义 RPC 端点
  3. 03配置令牌、会话等认证方式
  4. 04检查权限并校验输入
  5. 05为耗时操作安排后台任务

适用场景

  1. 01为 DocType 提供 CRUD 接口
  2. 02向前端开放自定义业务操作
  3. 03接收外部系统回调
  4. 04运行导出等耗时任务并查询状态

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/lubusin/frappe-skills --skill frappe-api-development

安装后在 Claude Code 中输入/frappe-api-development确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
authentication.md
oauth.md
permissions.md
python-api.md
rate-limiting.md
rest-api.md
server-scripts.md
webhooks.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

升级处理

参考资料

防护措施

  • 始终验证输入:切勿信任客户端数据;在服务端验证类型、长度和格式
  • 使用权限回调:在白名单方法中显式检查 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