模板 (Templates)
ent 接受外部的 Go 模板,可通过 --template 标志执行。
若模板名称已被 ent 定义,则会覆盖现有模板;否则会将执行输出写入与模板同名的文件中。例如:
stringer.tmpl - 此模板示例将写入名为 ent/stringer.go 的文件中。
{{/* 以下行告知 Intellij/GoLand 启用基于 *gen.Graph 类型的自动补全功能 */}}
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
{{ define "stringer" }}
{{/* 为生成的文件添加基础头部 */}}
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}
{{/* 遍历所有节点并实现 "GoStringer" 接口 */}}
{{ range $n := $.Nodes }}
{{ $receiver := $n.Receiver }}
func ({{ $receiver }} *{{ $n.Name }}) GoString() string {
if {{ $receiver }} == nil {
return fmt.Sprintf("{{ $n.Name }}(nil)")
}
return {{ $receiver }}.String()
}
{{ end }}
{{ end }}
debug.tmpl - 此模板示例将写入名为 ent/debug.go 的文件中。
{{ define "debug" }}
{{/* 用于为每个客户端 <T> 添加调试模式运行功能的模板 */}}
{{/* 为生成的文件添加基础头部 */}}
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}
{{/* 遍历所有节点并为 "Debug" 方法添加选项 */}}
{{ range $n := $.Nodes }}
{{ $client := print $n.Name "Client" }}
func (c *{{ $client }}) Debug() *{{ $client }} {
if c.debug {
return c
}
cfg := config{driver: dialect.Debug(c.driver, c.log), log: c.log, debug: true, hooks: c.hooks}
return &{{ $client }}{config: cfg}
}
{{ end }}
{{ end }}
若要覆盖现有模板,请使用其名称。例如:
{{/* 用于向特定类型添加额外字段的模板 */}}
{{ define "model/fields/additional" }}
{{- /* 向 "Card" 实体添加静态字段 */}}
{{- if eq $.Name "Card" }}
// 由模板定义的静态字段。
StaticField string `json:"static_field,omitempty"`
{{- end }}
{{ end }}
辅助模板
如上所述,ent 会将每个模板的执行输出写入与模板同名的文件中。
例如,定义为 {{ define "stringer" }} 的模板输出将写入名为 ent/stringer.go 的文件。
默认情况下,ent 会将每个用 {{ define "<name>" }} 声明的模板写入文件。但有时可能需要定义辅助模板——这些模板不会被直接调用,而是由其他模板执行。为支持这种用例,ent 支持两种将模板指定为辅助模板的命名格式:
格式如下:
1. {{ define "helper/.+" }} 用于全局辅助模板。例如:
{{ define "helper/foo" }}
{{/* 此处放置逻辑 */}}
{{ end }}
{{ define "helper/bar/baz" }}
{{/* 此处放置逻辑 */}}
{{ end }}
2. {{ define "<root-template>/helper/.+" }} 用于本地辅助模板。若模板的执行输出被写入文件,则视为“根”模板。例如:
{{/* 在 `gen.Graph` 上执行的根模板,将被写入名为 `ent/http.go` 的文件中 */}}
{{ define "http" }}
{{ range $n := $.Nodes }}
{{ template "http/helper/get" $n }}
{{ template "http/helper/post" $n }}
{{ end }}
{{ end }}
{{/* 在 `gen.Type` 上执行的辅助模板 */}}
{{ define "http/helper/get" }}
{{/* 此处放置逻辑 */}}
{{ end }}
{{/* 在 `gen.Type` 上执行的辅助模板 */}}
{{ define "http/helper/post" }}
{{/* 此处放置逻辑 */}}
{{ end }}
注解
Schema 注解允许将元数据附加到字段和边上,并将其注入到外部模板中。
注解必须是一个可序列化为 JSON 原始值的 Go 类型(例如结构体、映射或切片),并实现 Annotation 接口。
以下是在 schema 和模板中使用注解的示例:
1. 注解定义:
package entgql
// Annotation 用于为模板向字段添加元数据。
type Annotation struct {
// OrderField 是 graphql schema 中定义的排序字段。
OrderField string
}
// Name 实现 ent.Annotation 接口。
func (Annotation) Name() string {
return "EntGQL"
}
2. 在 ent/schema 中使用注解:
// User schema.
type User struct {
ent.Schema
}
// 用户的字段。
func (User) Fields() []ent.Field {
return []ent.Field{
field.Time("creation_date").
Annotations(entgql.Annotation{
OrderField: "CREATED_AT",
}),
}
}
3. 在外部模板中使用注解:
{{ range $node := $.Nodes }}
{{ range $f := $node.Fields }}
{{/* 通过名称获取注解。参见:Annotation.Name */}}
{{ if $annotation := $f.Annotations.EntGQL }}
{{/* 从注解中获取字段 */}}
{{ $orderField := $annotation.OrderField }}
{{ end }}
{{ end }}
{{ end }}
全局注解
全局注解是一种注入到 gen.Config 对象中的注解类型,可以在所有模板中全局访问。例如,一个包含配置文件信息(如 gqlgen.yml 或 swagger.yml)的注解,可以在所有模板中访问:
1. 注解定义:
package gqlconfig
import (
"entgo.io/ent/schema"
"github.com/99designs/gqlgen/codegen/config"
)
// Annotation 定义了一个自定义注解,
// 用于全局注入到所有模板中。
type Annotation struct {
Config *config.Config
}
func (Annotation) Name() string {
return "GQL"
}
var _ schema.Annotation = (*Annotation)(nil)
2. 在 ent/entc.go 中使用注解:
func main() {
cfg, err := config.LoadConfig("<gqlgen.yml 的路径>")
if err != nil {
log.Fatalf("加载 gqlgen 配置失败: %v", err)
}
opts := []entc.Option{
entc.TemplateDir("./template"),
entc.Annotations(gqlconfig.Annotation{Config: cfg}),
}
err = entc.Generate("./schema", &gen.Config{
Templates: entgql.AllTemplates,
}, opts...)
if err != nil {
log.Fatalf("运行 ent 代码生成失败: %v", err)
}
}
3. 在外部模板中使用注解:
{{- with $.Annotations.GQL.Config.StructTag }}
{{/* 在 *gen.Graph 上访问 GQL 配置 */}}
{{- end }}
{{ range $node := $.Nodes }}
{{- with $node.Config.Annotations.GQL.Config.StructTag }}
{{/* 在 *gen.Type 上访问 GQL 配置 */}}
{{- end }}
{{ end }}
示例
文档
模板在特定节点类型或整个 schema 图上执行。有关 API 文档,请参阅 GoDoc。
自动补全
JetBrains 用户可以添加以下模板注释以在其模板中启用自动补全:
{{/* 以下行告知 Intellij/GoLand 启用基于 *gen.Graph 类型的自动补全功能 */}}
{{/* gotype: entgo.io/ent/entc/gen.Graph */}}
{{ define "template" }}
{{/* ... */}}
{{ end }}
实际效果如下:
