TLDR;如何在Buffalo框架中具有外键(或通常具有db关系)的模型上创建REST api?
我绝对是初学者,并且我尝试按照其官方网站上给出的以下示例使用buffalo框架编写RESTFul服务。我能够在没有数据库关系的模型上创建RESTful api。但是,当我遇到模型具有外键的情况时,我会陷入困境。我在网络上找不到任何文档或参考。我在Go上的概念也很弱,您也可以在这些基础上对我进行教育。
型号:(参考号:https://gobuffalo.io/en/docs/db/relations#example
type Composer struct {
ID uuid.UUID `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Description string `json:"description" db:"description"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
type Track struct {
ID uuid.UUID `json:"id" db:"id"`
Title string `json:"title" db:"title"`
Description string `json:"description" db:"description"`
Composer Composer `has_one:"composer" fk_id:"id"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}
资源:(参考号:https://gobuffalo.io/en/docs/resources)
type TrackResource struct {
buffalo.Resource
}
func (v TrackResource) List(c buffalo.Context) error {
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
pieces := &models.Tracks{}
q := tx.PaginateFromParams(c.Params())
if err := q.All(pieces); err != nil {
return errors.WithStack(err)
}
c.Set("pagination", q.Paginator)
return c.Render(200, r.JSON(pieces))
}
func (v TrackResource) Show(c buffalo.Context) error {
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
piece := &models.Track{}
if err := tx.Find(piece, c.Param("track_id")); err != nil {
return c.Render(404, r.JSON(err))
}
return c.Render(200, r.JSON(piece))
}
func (v TrackResource) Create(c buffalo.Context) error {
piece := &models.Track{}
if err := c.Bind(piece); err != nil {
return errors.WithStack(err)
}
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
verrs, err := piece.Create(tx)
if err != nil {
return errors.WithStack(err)
}
if verrs.HasAny() {
return c.Render(422, r.JSON(verrs))
}
return c.Render(201, r.Auto(c, piece))
}
func (v TrackResource) Update(c buffalo.Context) error {
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
piece := &models.Track{}
if err := tx.Find(piece, c.Param("track_id")); err != nil {
return c.Error(404, err)
}
if err := c.Bind(piece); err != nil {
return errors.WithStack(err)
}
verrs, err := piece.Update(tx)
if err != nil {
return errors.WithStack(err)
}
if verrs.HasAny() {
return c.Render(422, r.JSON(verrs))
}
return c.Render(200, r.JSON(piece))
}
func (v TrackResource) Destroy(c buffalo.Context) error {
tx, ok := c.Value("tx").(*pop.Connection)
if !ok {
return errors.WithStack(errors.New("no transaction found"))
}
piece := &models.Track{}
if err := tx.Find(piece, c.Param("track_id")); err != nil {
return c.Error(404, err)
}
if err := tx.Destroy(piece); err != nil {
return errors.WithStack(err)
}
return c.Render(200, r.JSON(piece))
}
当我尝试创建曲目时。我遇到错误:
json: cannot unmarshal string into Go struct field Track.Composer of type models.Composer
gitlab.com/****/****/actions.TrackResource.Create
请帮助。
答案 0 :(得分:2)
您正在尝试将包含Track
的{{1}}与其ID绑定,但是Composer
被定义为结构。
要使其工作,您需要实现Unmarshaler接口并定义如何将此ID转换为所需的Composer
结构。
答案 1 :(得分:0)
您应该在ComposerID
结构中添加一个Track
字段。然后,您可以使用Eager
或Load
,然后pop将为您加载关联的Composer
对象。这已显示在您链接到的页面上,以供模型参考。