REST API
Frappe框架可以直接为您的所有DocTypes生成REST API。您还可以使用它们的 模块名. 方法 运行任意Python方法。
https://www.youtube.com/embed/c1gJIYr77sk
授权机制
有两种方法可以通过Frappe REST API进行身份验证。基于令牌的身份验证和基于密码的身份验证。
1. 基于令牌
令牌是API密钥和API秘钥的组合。首先,您必须创建一个API用户,然后在用户的设置中, 通过 API访问 生成密钥。
通过将api_key和api_secret用冒号:连接起来生成令牌。将字符串token api_key:api_secret传递到请求的Authorization标头中即可。
fetch('http://<base-url>/api/method/frappe.auth.get_logged_user', {
headers: {
'Authorization': 'token api_key:api_secret'
}
})
.then(r => r.json())
.then(r => {
console.log(r);
})
➜ curl http://<base-url>/api/method/frappe.auth.get_logged_user -H "Authorization: token api_key:api_secret"
注意:
base 64的生成地址: https://www.base64encode.org/
云端的frappe cloud 验证的代码:
Authorization: token 这里写base64编码
如果在本机开发, 则用如下的验证代码
Authorization: Basic 这里写base64编码
2. 基于账号密码验证
基于密码的身份验证依赖于 cookie 和会话数据来维护后续请求中的身份验证。在大多数情况下,您用于发出 REST 调用的将处理会话数据,但如果没法处理,则应使用基于令牌的身份验证(意思是: 有部分接口访问, 单纯通过基于密码的验证是没法访问的)。
fetch('http://<base-url>/api/method/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
usr: 'username or email',
pwd: 'password'
})
})
.then(r => r.json())
.then(r => {
console.log(r);
})
➜ curl --cookie-jar snowcookie --request POST "http://<base-url>/api/method/login" -H 'Content-Type: application/json' -H 'Accept: application/json' --data-raw "{ \"usr\" : \"<username>\", \"pwd\": \"<password>\" }"
{"message":"Logged In","home_page":"/app","full_name":"<user:full_name>","dashboard_route":"/sites"}
➜ curl --cookie snowcookie --request POST "http://<base-url>/api/method/frappe.auth.get_logged_user" -H 'Accept: application/json'
{"message":"<username>"}
3. 访问令牌
请参考文档了解 如何设置OAuth。
在请求头中使用生成的access_token
。
fetch('http://<base-url>/api/method/frappe.auth.get_logged_user', {
headers: {
'Authorization': 'Bearer access_token'
}
})
.then(r => r.json())
.then(r => {
console.log(r);
})
列出单据类
To get a list of records of a DocType, send a GET request at /api/resource/:doctype
. By default, it will return 20 records and will only fetch the name of the records. The result for the query can be found under data
of the payload.
We'll be using the ToDo DocType to show example responses for the queries below.
GET /api/resource/:doctype
Response
{
"data":[
{"name":"f765eef382"},
{"name":"2a26fa1c64"},
{"name":"f32c68060f"},
{"name":"9065fa9832"},
{"name":"419082fc38"},
{"name":"6234d15099"},
{"name":"62f2181ee0"},
{"name":"a50afbbfaa"},
...
]
}
You can specify which fields to fetch in the fields
param. It should be a JSON array.
GET /api/resource/:doctype?fields=["field1", "field2"]
Response
{
"data":[
{"description":"Business worker talk society. Each try theory prove notice middle. Crime couple trouble guy project hit.","name":"f765eef382"},
{"description":"This reveal as look near sister. Car staff bar specific address.","name":"2a26fa1c64"},
{"description":"Wear bag some walk. Movie partner new class tough run. Brother Democrat imagine.","name":"f32c68060f"},
{"description":"Break laugh apply reveal new now focus heavy. Outside local staff research total. Else point try despite.","name":"9065fa9832"},
{"description":"Truth reduce baby artist actually model. Cost phone us others himself wife almost. Language thing wonder share talk. Factor glass significant could window certain yet.","name":"419082fc38"},
{"description":"Tv memory understand opportunity window beat physical.","name":"6234d15099"},
{"description":"Should floor situation in response sell. Our assume company mean red majority shoulder.","name":"62f2181ee0"},
{"description":"Performance seem sign recent. Court form me tonight simple trouble. Address job garden play teach. Happy speech amount offer change then.","name":"a50afbbfaa"},
...
]
}
You can filter the records by passing filters
param. Filters should be an array, where each filter is of the format: [field, operator, value]
GET /api/resource/:doctype?filters=[["field1", "=", "value1"], ["field2", ">", "value2"]]
Response
{
"data":[
{"name":"f765eef382"},
{"name":"2a26fa1c64"},
{"name":"f32c68060f"},
{"name":"9065fa9832"},
{"name":"419082fc38"},
{"name":"6234d15099"},
{"name":"62f2181ee0"},
{"name":"a50afbbfaa"},
...
]
}
filters
parameter joins all the specified filters using AND
SQL operator, if you want OR
filters you can use the or_filters
param. Syntax for or_filters
is same as `filters.
You can also provide the sort field and order. It should be of the format fieldname asc
or fieldname desc
. The space should be URL encoded. In the following line, we're taking fieldname to be title
.
GET /api/resource/:doctype?order_by=title%20desc
You can also page the results by providing the limit_start
and limit_page_length
params.
GET /api/resource/:doctype?limit_start=5&limit_page_length=10
Response
{
"data": [
{"name":"6234d15099"},
{"name":"62f2181ee0"},
{"name":"a50afbbfaa"},
{"name":"aa12a5cf71"},
{"name":"6ac9800d4e"},
{"name":"4bcf8b701c"},
{"name":"aee15f4c20"},
{"name":"6ba753afef"},
...
]
}
limit
is an alias for limit_page_length
for accessing /api/resource
in Version 13. This means the following should also return the same payload as the above query.
GET /api/resource/:doctype?limit_start=5&limit=10
By default, you will receive the data as List[dict]
. You can retrieve your data as List[List]
by passing as_dict=False
.
GET /api/resource/:doctype?limit_start=5&limit=5&as_dict=False
Response
{
"data": [
["6234d15099"],
["62f2181ee0"],
["a50afbbfaa"],
["aa12a5cf71"],
["6ac9800d4e"]
]
}
To debug the query built for your reqeusts, you can pass debug=True
with the request. This returns the executed query and execution time under exc
of the payload.
GET /api/resource/:doctype?limit_start=10&limit=5&debug=True
Response
{
"data": [
{"name":"4bcf8b701c"},
{"name":"aee15f4c20"},
{"name":"6ba753afef"},
{"name":"f4b7e24abc"},
{"name":"bd9156096c"}
],
"exc": "[\"select `tabToDo`.`name`\\n\\t\\t\\tfrom `tabToDo`\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t order by `tabToDo`.`modified` DESC\\n\\t\\t\\tlimit 5 offset 10\", \"Execution time: 0.0 sec\"]"
}
CRUD Operations
Frappe generates REST endpoints for CRUD operations for all DocTypes automatically. Make sure you set the following headers in your requests so that you get proper JSON responses.
{
"Accept": "application/json",
"Content-Type": "application/json",
}
Create
Create a new document by sending a POST
request to /api/resource/:doctype
. Send the document as JSON in the Request Body.
POST /api/resource/:doctype
# Body
{"description": "New ToDo"}
Response
{
"data": {
"name": "af2e2d0e33",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:19:00.281026",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "New ToDo",
"doctype": "ToDo"
}
}
Read
Get a document by sending a GET
request to /api/resource/:doctype/:name
.
GET /api/resource/:doctype/:name
Response
{
"data": {
"name": "bf2e760e13",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:19:00.281026",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "<p>Test description</p>",
"doctype": "ToDo"
}
}
Update
Update a document by sending a PUT
request to /api/resource/:doctype/:name
. You don't need to send the whole document, instead you can just send the fields that you want to update.
PUT /api/resource/:doctype/:name
# Body
{"description": "New description"}
Response
{
"data": {
"name": "bf2e760e13",
"owner": "Administrator",
"creation": "2019-06-03 14:19:00.281026",
"modified": "2019-06-03 14:21:00.785117",
"modified_by": "Administrator",
"idx": 0,
"docstatus": 0,
"status": "Open",
"priority": "Medium",
"description": "New description",
"doctype": "ToDo"
}
}
Delete
Delete a document by sending a DELETE
request to /api/resource/:doctype/:name
.
DELETE /api/resource/:doctype/:name
Response
{"message": "ok"}
Remote Method Calls
Frappe allows you to trigger arbitrary python methods using the REST API for handling custom logic. These methods must be marked as whitelisted to make them accessible via REST.
To run a whitelisted python method at frappe.auth.get_logged_user
, send a request to the endpoint /api/method/frappe.auth.get_logged_user
.
GET /api/method/frappe.auth.get_logged_user
Response
{
"message": "[email protected]"
}
- If your method returns some values, you should send a
GET
request. - If your method changes the state of the database, use
POST
. After a successfulPOST
request, the framework will automatically callfrappe.db.commit()
to commit the changes to the database. - A successful response will return a JSON object with a
message
key. - An errored response will return a JSON object with
exc
key which contains the stack trace andexc_type
which contains the thrown Exception. - The return value of the method will be converted to a JSON and sent as the response.
File Uploads
There is a dedicated method /api/method/upload_file
that accepts binary file data and uploads it into the system.
Here is the curl command for it:
➜ curl -X POST \
http://<base-url>/api/method/upload_file \
-H 'Accept: application/json' \
-H 'Authorization: token xxxx:yyyy' \
-F file=@/path/to/file/file.png
If you are using client side Javascript to upload files, you can append the uploaded files as FormData and send an XHR request. Here is the implementation code in Frappe Desk.