Content Types
API 参考
自动生成的路由、访问控制级别、规则引擎、查询参数和缓存。
每个内容类型自动获得 REST API。本页介绍生成的路由、访问控制、过滤和查询参数。
自动生成的路由
Collection 类型(默认)
RESTful 模式(默认):
| 方法 | 路由 | 操作 |
|---|---|---|
| GET | /api/v1/cms/{plural} | 列表 |
| GET | /api/v1/cms/{plural}/{id} | 详情 |
| POST | /api/v1/cms/{plural} | 创建 |
| PUT | /api/v1/cms/{plural}/{id} | 更新 |
| DELETE | /api/v1/cms/{plural}/{id} | 删除 |
Simple 模式(当 api_restful = false 时):
| 方法 | 路由 | 操作 |
|---|---|---|
| GET | /api/v1/cms/{plural} | 列表 |
| GET | /api/v1/cms/{plural}/{id} | 详情 |
| POST | /api/v1/cms/{plural}/create | 创建 |
| POST | /api/v1/cms/{plural}/{id}/update | 更新 |
| POST | /api/v1/cms/{plural}/{id}/delete | 删除 |
Single 类型
| 方法 | 路由 | 操作 |
|---|---|---|
| GET | /api/v1/cms/{singular} | 获取唯一记录(首次请求自动创建) |
| PUT | /api/v1/cms/{singular} | 更新唯一记录 |
管理路由
每个内容类型还会在 /api/v1/admin/cms/ 下获得管理路由:
| 方法 | 路由 | 操作 |
|---|---|---|
| GET | /api/v1/admin/cms/{plural} | 列出所有记录(绕过过滤器) |
| GET | /api/v1/admin/cms/{plural}/{id} | 获取任意记录 |
| POST | /api/v1/admin/cms/{plural} | 创建记录 |
| PUT | /api/v1/admin/cms/{plural}/{id} | 更新记录 |
| DELETE | /api/v1/admin/cms/{plural}/{id} | 删除记录 |
管理路由绕过 filter 和 filter_auth 规则,且始终显示 private 字段。
访问控制
在 TOML 定义中控制每个端点的访问权限:
[content_type.api.list]
access = "public"
cache = true
filter = 'status = "published"'
fields = ["title", "cover", "price"]
[content_type.api.create]
access = "admin"
[content_type.api.update]
access = "admin"
[content_type.api.delete]
access = "admin"访问级别
| 级别 | 含义 |
|---|---|
none | 完全拒绝 — 返回 403 |
public | 无需认证 |
member | 任何已登录用户 |
admin | 需要管理员角色 |
默认访问级别
| 端点 | 默认 |
|---|---|
list | public |
get | public |
create | member |
update | member |
delete | admin |
端点选项
| 选项 | 类型 | 说明 |
|---|---|---|
access | string | 访问级别:none、public、member、admin |
filter | string | 对所有请求生效的规则表达式 |
filter_auth | string | 为已登录用户额外添加 OR 规则 |
cache | bool | 启用服务端响应缓存 |
fields | string[] | 返回字段白名单 |
规则引擎
用表达式过滤数据,编译为 SQL WHERE 子句:
[content_type.api.list]
filter = 'status = "published" && price > 0'
filter_auth = 'created_by = @request.auth.id'filter 对所有请求生效。filter_auth 为已登录用户添加 OR 条件。组合逻辑:filter OR (已认证 AND filter_auth)。
运算符
| 运算符 | 含义 | 示例 |
|---|---|---|
= | 等于 | status = "published" |
!= | 不等于 | status != "draft" |
> >= < <= | 比较 | price > 0 |
~ | LIKE 匹配 | title ~ "%rust%" |
!~ | NOT LIKE | title !~ "%spam%" |
&& | AND | a = 1 && b = 2 |
|| | OR | a = 1 || b = 2 |
变量
| 变量 | 说明 |
|---|---|
@request.auth.id | 当前登录用户 ID |
@request.auth.role | 当前用户角色 |
@request.body.* | 请求体字段值 |
@request.query.* | URL 查询参数值 |
@now | 当前时间戳 |
特殊语法
| 语法 | 含义 | 示例 |
|---|---|---|
field:isset | 字段非空 | avatar:isset |
field:length > N | 字符串/数组长度 | tags:length > 0 |
null | 空值 | deleted_at = null |
true / false | 布尔值 | is_free = false |
示例
# 公开仅可见已发布的内容
filter = 'status = "published"'
# 已发布或属于当前用户
filter = 'status = "published"'
filter_auth = 'created_by = @request.auth.id'
# 复杂过滤(带分组)
filter = '(status = "published" && price > 0) || featured = true'查询参数
GET /api/v1/cms/courses?page=2&page_size=10&sort=created_at:desc&status=published&include=instructor,tags| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
page | int | 1 | 页码 |
page_size | int | 20 | 每页条数(有上限) |
sort | string | — | 排序:field:asc 或 field:desc,逗号分隔多个 |
search | string | — | 全文搜索词 |
include | string | — | 逗号分隔的关联字段,填充为完整记录 |
skip_total | bool | false | 跳过 COUNT 查询,返回 total: -1,提升性能 |
{field} | string | — | 按字段值精确过滤 |
__meta.{path} | string | — | 按 JSON 元数据路径过滤 |
分页响应
{
"items": [...],
"total": 42,
"page": 2,
"page_size": 10
}排序示例
# 单字段
?sort=created_at:desc
# 多字段
?sort=status:asc,created_at:desc过滤示例
# 精确匹配
?status=published
# 多个过滤
?status=published&level=beginner
# 元数据过滤(需要 metaable 协议)
?__meta.featured=true响应缓存
按端点启用缓存:
[content_type.api.list]
cache = true缓存响应存储在内存中,以查询哈希为键。对该内容类型的任何写操作(创建、更新、删除)都会自动清除缓存。
缓存 TTL 通过 cms_cache_ttl_secs 配置(默认 30 秒)。
私有字段
标记为 private = true 的字段会从公开 API 响应中排除:
[[fields]]
name = "internal_notes"
field_type = "text"
private = true- 公开 API(
/api/v1/cms/):私有字段从响应中移除 - 管理 API(
/api/v1/admin/cms/):私有字段始终包含
错误响应
| 状态码 | 含义 |
|---|---|
400 | 请求体或查询参数无效 |
401 | 需要认证 |
403 | 访问被拒(角色不匹配或 access = "none") |
404 | 记录不存在 |
409 | 冲突(乐观锁不匹配 — lockable 协议) |
422 | 验证失败(响应体含字段级详情) |
