Skip to main content

模块

¥Models

由于 Strapi 是一个无头内容管理系统 (CMS),因此为内容创建数据结构是使用该软件最重要的方面之一。模型定义数据结构的表示。

¥As Strapi is a headless Content Management System (CMS), creating a data structure for the content is one of the most important aspects of using the software. Models define a representation of the data structure.

Strapi 有 2 种不同类型的模型:

¥There are 2 different types of models in Strapi:

  • 内容类型,可以是集合类型或单一类型,具体取决于它们管理的条目数量,

    ¥content-types, which can be collection types or single types, depending on how many entries they manage,

  • 以及可在多种内容类型中重用的数据结构的组件。

    ¥and components that are data structures re-usable in multiple content-types.

如果你刚刚开始,直接在管理面板中使用 内容类型生成器 生成一些模型会很方便。用户界面接管了许多验证任务,并展示了可用于创建内容数据结构的所有选项。然后可以使用此文档在代码级别查看生成的模型映射。

¥If you are just starting out, it is convenient to generate some models with the Content-type Builder directly in the admin panel. The user interface takes over a lot of validation tasks and showcases all the options available to create the content's data structure. The generated model mappings can then be reviewed at the code level using this documentation.

模型创建

¥Model creation

内容类型和组件模型的创建和存储方式不同。

¥Content-types and components models are created and stored differently.

内容类型

¥Content-types

可以在 Strapi 中创建内容类型:

¥Content-types in Strapi can be created:

内容类型使用以下文件:

¥The content-types use the following files:

  • schema.json 表示模型的 schema 定义。(使用任一方法创建内容类型时自动生成)

    ¥schema.json for the model's schema definition. (generated automatically, when creating content-type with either method)

  • lifecycles.js生命周期钩子。该文件必须手动创建。

    ¥lifecycles.js for lifecycle hooks. This file must be created manually.

这些模型文件存储在 ./src/api/[api-name]/content-types/[content-type-name]/ 中,在这些文件夹中找到的任何 JavaScript 或 JSON 文件都将作为内容类型的模型加载(请参阅 项目结构)。

¥These models files are stored in ./src/api/[api-name]/content-types/[content-type-name]/, and any JavaScript or JSON file found in these folders will be loaded as a content-type's model (see project structure).

注意

在启用 TypeScript 的项目中,可以使用 ts:generate-types 命令生成模式类型。

¥In TypeScript-enabled projects, schema typings can be generated using the ts:generate-types command.

组件

¥Components

无法使用 CLI 工具创建组件模型。使用 内容类型生成器 或手动创建它们。

¥Component models can't be created with CLI tools. Use the Content-type Builder or create them manually.

组件模型存储在 ./src/components 文件夹中。每个组件都必须位于一个子文件夹中,该子文件夹以该组件所属的类别命名(参见 项目结构)。

¥Components models are stored in the ./src/components folder. Every component has to be inside a subfolder, named after the category the component belongs to (see project structure).

模型架构

¥Model schema

模型的 schema.json 文件包含:

¥The schema.json file of a model consists of:

  • settings,例如模型表示的内容类型类型或应存储数据的表名称,

    ¥settings, such as the kind of content-type the model represents or the table name in which the data should be stored,

  • information,主要用于在管理面板中显示模型并通过 REST 和 GraphQL API 访问它,

    ¥information, mostly used to display the model in the admin panel and access it through the REST and GraphQL APIs,

  • attributes,描述模型的数据结构,

    ¥attributes, which describe the data structure of the model,

  • options 用于定义模型上的特定行为。

    ¥and options used to defined specific behaviors on the model.

模型设置

¥Model settings

模型的常规设置可以使用以下参数进行配置:

¥General settings for the model can be configured with the following parameters:

范围类型描述
collectionName字符串应存储数据的数据库表名称
kind

可选,
仅适用于内容类型
字符串定义内容类型是否为:
  • 集合类型 (collectionType)
  • 还是单一类型 (singleType)
// ./src/api/[api-name]/content-types/restaurant/schema.json

{
"kind": "collectionType",
"collectionName": "Restaurants_v1",
}

型号信息

¥Model information

模型架构中的 info 键描述了用于在管理面板中显示模型并通过 Content API 访问模型的信息。它包括以下参数:

¥The info key in the model's schema describes information used to display the model in the admin panel and access it through the Content API. It includes the following parameters:

范围类型描述
displayName字符串在管理面板中使用的默认名称
singularName字符串内容类型名称的单数形式。
用于生成 API 路由和数据库/表集合。

应该是短横线大小写。
pluralName字符串内容类型名称的复数形式。
用于生成 API 路由和数据库/表集合。

应该是短横线大小写。
description字符串型号说明
./src/api/[api-name]/content-types/restaurant/schema.json

"info": {
"displayName": "Restaurant",
"singularName": "restaurant",
"pluralName": "restaurants",
"description": ""
},

模型属性

¥Model attributes

模型的数据结构由属性列表组成。每个属性都有一个 type 参数,该参数描述其性质并将属性定义为简单的数据片段或 Strapi 使用的更复杂的结构。

¥The data structure of a model consists of a list of attributes. Each attribute has a type parameter, which describes its nature and defines the attribute as a simple piece of data or a more complex structure used by Strapi.

有多种类型的属性可用:

¥Many types of attributes are available:

  • 标量类型(例如字符串、日期、数字、布尔值等),

    ¥scalar types (e.g. strings, dates, numbers, booleans, etc.),

  • Strapi 特定类型,例如:

    ¥Strapi-specific types, such as:

    • media 表示通过 媒体库 上传的文件

      ¥media for files uploaded through the Media library

    • relation 描述内容类型之间的 relation

      ¥relation to describe a relation between content-types

    • customField 描述 自定义字段 及其具体按键

      ¥customField to describe custom fields and their specific keys

    • component 定义 component(即可用于多种内容类型的数据结构)

      ¥component to define a component (i.e. a data structure usable in multiple content-types)

    • dynamiczone 定义 动态区(即基于组件列表的灵活空间)

      ¥dynamiczone to define a dynamic zone (i.e. a flexible space based on a list of components)

    • 以及 localelocalizations 类型,仅由 国际化 (i18n) 插件 使用

      ¥and the locale and localizations types, only used by the Internationalization (i18n) plugin

属性的 type 参数应为以下值之一:

¥The type parameter of an attribute should be one of the following values:

类型类别可用类型
字符串类型
日期类型
号码类型
其他通用类型
Strapi 独有的特殊类型
国际化 (i18n) 相关类型

仅当在内容类型上启用 国际化 时才可使用

验证

¥Validations

可以使用以下参数将基本验证应用于属性:

¥Basic validations can be applied to attributes using the following parameters:

范围类型描述默认
required布尔值如果是 true,则为此属性添加必需的验证器false
max整数检查该值是否大于或等于给定的最大值*
min整数检查该值是否小于或等于给定的最小值*
minLength整数字段输入值的最小字符数*
maxLength整数字段输入值的最大字符数*
private布尔值如果 true,该属性将从服务器响应中删除。

💡这对于隐藏敏感数据很有用。
false
configurable布尔值如果是 false,则无法通过 Content-type Builder 插件配置该属性。true
./src/api/[api-name]/content-types/restaurant/schema.json

{
// ...
"attributes": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 99,
"unique": true
},
"description": {
"default": "My description",
"type": "text",
"required": true
},
"slug": {
"type": "uid",
"targetField": "title"
}
// ...
}
}

数据库验证和设置

¥Database validations and settings

🚧 此 API 被认为是实验性的。

这些设置应保留给高级用途,因为它们可能会破坏某些功能。没有计划使这些设置稳定。

¥These settings should be reserved to an advanced usage, as they might break some features. There are no plans to make these settings stable.

数据库验证和设置是在架构迁移期间直接传递到 tableBuilder Knex.js 函数的自定义选项。数据库验证允许对自定义列设置进行高级控制。以下选项在每个属性的 column: {} 对象中设置:

¥Database validations and settings are custom options passed directly onto the tableBuilder Knex.js function during schema migrations. Database validations allow for an advanced degree of control for setting custom column settings. The following options are set in a column: {} object per attribute:

范围类型描述默认
namestring更改数据库中列的名称*
defaultTostring设置数据库 defaultTo,通常与 notNullable 一起使用*
notNullable布尔值设置数据库 notNullable,确保列不能为空false
unsigned布尔值仅适用于数字列,消除了负数的能力,但最大长度加倍false
unique布尔值强制数据库级别唯一,使用草稿和发布功能时请小心false
typestring更改数据库类型,如果 type 有参数,则应将它们传递到 args*
argsarray传递到 Knex.js 函数的参数会更改 type 等内容[]
./src/api/[api-name]/content-types/restaurant/schema.json

{
// ...
"attributes": {
"title": {
"type": "string",
"minLength": 3,
"maxLength": 99,
"unique": true,
"column": {
"unique": true // enforce database unique also
}
},
"description": {
"default": "My description",
"type": "text",
"required": true,
"column": {
"defaultTo": "My description", // set database level default
"notNullable": true // enforce required at database level, even for drafts
}
},
"rating": {
"type": "decimal",
"default": 0,
"column": {
"defaultTo": 0,
"type": "decimal", // using the native decimal type but allowing for custom precision
"args": [
6,1 // using custom precision and scale
]
}
}
// ...
}
}

uid

¥uid type

uid 类型用于根据 2 个可选参数,使用唯一标识符 (UID)(例如文章的别名)自动预填充管理面板中的字段值:

¥The uid type is used to automatically prefill the field value in the admin panel with a unique identifier (UID) (e.g. slugs for articles) based on 2 optional parameters:

  • targetField(字符串):如果使用,定义为目标的字段值将用于自动生成 UID。

    ¥targetField (string): If used, the value of the field defined as a target is used to auto-generate the UID.

  • options(字符串):如果使用,则 UID 是根据传递给 底层 uid 生成器 的一组选项生成的。生成的 uid 必须匹配以下正则表达式模式:/^[A-Za-z0-9-_.~]*$

    ¥options (string): If used, the UID is generated based on a set of options passed to the underlying uid generator. The resulting uid must match the following regular expression pattern: /^[A-Za-z0-9-_.~]*$.

关系

¥Relations

关系将内容类型链接在一起。关系在模型的 attributestype: 'relation' 中明确定义,并接受以下附加参数:

¥Relations link content-types together. Relations are explicitly defined in the attributes of a model with type: 'relation' and accept the following additional parameters:

范围描述
relation这些值之间的关系类型:
  • oneToOne
  • oneToMany
  • manyToOne
  • manyToMany
target接受字符串值作为目标内容类型的名称
mappedByinversedBy

可选
在双向关系中,拥有方声明 inversedBy 密钥,而反向方声明 mappedBy 密钥

当一个条目只能链接到另一个条目时,一对一关系非常有用。

¥One-to-One relationships are useful when one entry can be linked to only one other entry.

它们可以是单向的或双向的。在单向关系中,只能查询其中一个模型及其链接项。

¥They can be unidirectional or bidirectional. In unidirectional relationships, only one of the models can be queried with its linked item.

Unidirectional use case example:
  • 博客文章属于一个类别。

    ¥A blog article belongs to a category.

  • 查询一篇文章可以检索它的类别,

    ¥Querying an article can retrieve its category,

  • 但查询类别不会检索拥有的文章。

    ¥but querying a category won't retrieve the owned article.

./src/api/[api-name]/content-types/article/schema.json

// …
attributes: {
category: {
type: 'relation',
relation: 'oneToOne',
target: 'category',
},
},
// …
Bidirectional use case example:
  • 博客文章属于一个类别。

    ¥A blog article belongs to a category.

  • 查询一篇文章可以检索它的类别,

    ¥Querying an article can retrieve its category,

  • 查询类别也会检索其拥有的文章。

    ¥and querying a category also retrieves its owned article.

./src/api/[api-name]/content-types/article/schema.json

// …
attributes: {
category: {
type: 'relation',
relation: 'oneToOne',
target: 'category',
inversedBy: 'article',
},
},
// …

./src/api/[api-name]/content-types/category/schema.json

// …
attributes: {
article: {
type: 'relation',
relation: 'oneToOne',
target: 'article',
mappedBy: 'category',
},
},
// …

自定义字段

¥Custom fields

自定义字段 通过向内容类型添加新类型的字段来扩展 Strapi 的功能。自定义字段在带有 type: customField 的模型的 attributes 中显式定义。自定义字段的属性还接受:

¥Custom fields extend Strapi’s capabilities by adding new types of fields to content-types. Custom fields are explicitly defined in the attributes of a model with type: customField. Custom fields' attributes also accept:

自定义字段的属性还显示以下特性:

¥Custom fields' attributes also show the following specificities:

  • customField 属性,其值充当唯一标识符,指示应使用哪个已注册的自定义字段。其值如下:

    ¥a customField attribute whose value acts as a unique identifier to indicate which registered custom field should be used. Its value follows:

    • 如果插件创建了自定义字段,则为 plugin::plugin-name.field-name 格式

      ¥either the plugin::plugin-name.field-name format if a plugin created the custom field

    • 或特定于当前 Strapi 应用的自定义字段的 global::field-name 格式

      ¥or the global::field-name format for a custom field specific to the current Strapi application

  • 以及其他参数,具体取决于注册自定义字段时定义的内容(参见 自定义字段文档)。

    ¥and additional parameters depending on what has been defined when registering the custom field (see custom fields documentation).

./src/api/[apiName]/[content-type-name]/content-types/schema.json

{
// …
"attributes": {
"attributeName": { // attributeName would be replaced by the actual attribute name
"type": "customField",
"customField": "plugin::color-picker.color",
"options": {
"format": "hex"
}
}
}
// …
}

组件

¥Components

组件字段创建内容类型和组件结构之间的关系。组件在具有 type: 'component' 的模型的 attributes 中显式定义,并接受以下附加参数:

¥Component fields create a relation between a content-type and a component structure. Components are explicitly defined in the attributes of a model with type: 'component' and accept the following additional parameters:

范围类型描述
repeatable布尔值可能是 truefalse,具体取决于组件是否可重复
component字符串定义相应的组件,格式如下:
<category>.<componentName>
./src/api/[apiName]/restaurant/content-types/schema.json

{
"attributes": {
"openinghours": {
"type": "component",
"repeatable": true,
"component": "restaurant.openinghours"
}
}
}

动态区域

¥Dynamic zones

动态区域创建了一个灵活的空间,可以根据 components 的混合列表在其中编写内容。

¥Dynamic zones create a flexible space in which to compose content, based on a mixed list of components.

动态区域在具有 type: 'dynamiczone' 的模型的 attributes 中明确定义。它们还接受 components 数组,其中每个组件应按照以下格式命名:<category>.<componentName>

¥Dynamic zones are explicitly defined in the attributes of a model with type: 'dynamiczone'. They also accept a components array, where each component should be named following this format: <category>.<componentName>.

./src/api/[api-name]/content-types/article/schema.json

{
"attributes": {
"body": {
"type": "dynamiczone",
"components": ["article.slider", "article.content"]
}
}
}

型号选择

¥Model options

options 键用于定义特定行为并接受以下参数:

¥The options key is used to define specific behaviors and accepts the following parameter:

范围类型描述
privateAttributes字符串数组允许将一组属性视为私有属性,即使它们实际上并未在模型中定义为属性。它可用于从 API 响应时间戳中删除它们。

模型中定义的 privateAttributes 与全局 Strapi 配置中定义的 privateAttributes 合并。
draftAndPublish布尔值启用草稿和发布功能。

默认值:true(如果内容类型是从交互式 CLI 创建的,则为 false)。
populateCreatorFields布尔值利用插件中的 createdByupdatedBy 钩子的插件开发者需要重构其代码。false
./src/api/[api-name]/content-types/restaurant/schema.json

{
"options": {
"privateAttributes": ["id", "createdAt"],
"draftAndPublish": true
}
}

生命周期钩子

¥Lifecycle hooks

生命周期钩子是调用 Strapi 查询时触发的函数。当通过管理面板管理内容或使用 queries· 开发自定义代码时,它们会自动触发

¥Lifecycle hooks are functions that get triggered when Strapi queries are called. They are triggered automatically when managing content through the administration panel or when developing custom code using queries·

生命周期钩子可以通过声明或编程方式自定义。

¥Lifecycle hooks can be customized declaratively or programmatically.

提醒

直接使用 knex 库而不是 Strapi 函数时,不会触发生命周期钩子。

¥Lifecycles hooks are not triggered when using directly the knex library instead of Strapi functions.

文档服务 API:生命周期和中间件

文档服务 API 根据调用的方法触发各种数据库生命周期钩子。有关完整参考,请参阅 文档服务 API:生命周期钩子。批量操作生命周期(createManyupdateManydeleteMany)永远不会由文档服务 API 方法触发。文档服务中间件 也可以实现。

¥The Document Service API triggers various database lifecycle hooks based on which method is called. For a complete reference, see Document Service API: Lifecycle hooks. Bulk actions lifecycles (createMany, updateMany, deleteMany) will never be triggered by a Document Service API method. Document Service middlewares can be implemented too.

可用的生命周期事件

¥Available lifecycle events

以下生命周期事件可用:

¥The following lifecycle events are available:

  • beforeCreate

  • beforeCreateMany

  • afterCreate

  • afterCreateMany

  • beforeUpdate

  • beforeUpdateMany

  • afterUpdate

  • afterUpdateMany

  • beforeDelete

  • beforeDeleteMany

  • afterDelete

  • afterDeleteMany

  • beforeCount

  • afterCount

  • beforeFindOne

  • afterFindOne

  • beforeFindMany

  • afterFindMany

钩子 event 对象

¥Hook event object

生命周期钩子是采用 event 参数的函数,该参数是具有以下键的对象:

¥Lifecycle hooks are functions that take an event parameter, an object with the following keys:

密钥类型描述
action字符串已触发的生命周期事件(参见 list
model字符串数组(uid)将监听其事件的内容类型的 uid 数组。
如果未提供此参数,则会监听所有内容类型的事件。
params目的接受以下参数:
  • data
  • select
  • where
  • orderBy
  • limit
  • offset
  • populate
result目的可选,仅适用于 afterXXX 事件

包含操作的结果。
state目的查询状态,可用于在查询的 beforeXXXafterXXX 事件之间共享状态。

声明式和编程式用法

¥Declarative and programmatic usage

要配置内容类型生命周期钩子,请在 ./src/api/[api-name]/content-types/[content-type-name]/ 文件夹中创建 lifecycles.js 文件。

¥To configure a content-type lifecycle hook, create a lifecycles.js file in the ./src/api/[api-name]/content-types/[content-type-name]/ folder.

每个事件监听器都会按顺序调用。它们可以是同步的或异步的。

¥Each event listener is called sequentially. They can be synchronous or asynchronous.

./src/api/[api-name]/content-types/[content-type-name]/lifecycles.js

module.exports = {
beforeCreate(event) {
const { data, where, select, populate } = event.params;

// let's do a 20% discount everytime
event.params.data.price = event.params.data.price * 0.8;
},

afterCreate(event) {
const { result, params } = event;

// do something to the result;
},
};

使用数据库层 API,还可以注册订阅者并以编程方式监听事件:

¥Using the database layer API, it's also possible to register a subscriber and listen to events programmatically:

./src/index.js
module.exports = {
async bootstrap({ strapi }) {
// registering a subscriber
strapi.db.lifecycles.subscribe({
models: [], // optional;

beforeCreate(event) {
const { data, where, select, populate } = event.params;

event.state = 'doStuffAfterWards';
},

afterCreate(event) {
if (event.state === 'doStuffAfterWards') {
}

const { result, params } = event;

// do something to the result
},
});

// generic subscribe for generic handling
strapi.db.lifecycles.subscribe((event) => {
if (event.action === 'beforeCreate') {
// do something
}
});
}
}