使用echo和gorm进行部分更新结构体。

huangapple go评论116阅读模式
英文:

Partial update a structure with echo and gorm

问题

我有一个用户界面、用户模型和用户ID结构。

  1. type UserId struct {
  2. Id int64 `param:"id" json:"id"`
  3. }
  4. type User struct {
  5. Email string `json:"email"`
  6. Password string `json:"password"`
  7. Username string `json:"username"`
  8. CreatedAt time.Time `json:"created_at"`
  9. UpdatedAt time.Time `json:"updated_at"`
  10. }
  11. type User struct {
  12. gorm.Model
  13. ID int64 `gorm:"primary_key"`
  14. Email string `gorm:"type:varchar(128);unique;not null"`
  15. Username string `gorm:"type:varchar(64);unique;not null"`
  16. Password string `gorm:"type:varchar(64);not null"`
  17. }

我有一个更新用户的函数。

  1. func updateUser(c echo.Context) error {
  2. cc := c.(*myproject.ConfigContext)
  3. userId := new(interfaces.UserId)
  4. err := cc.Bind(userId)
  5. if err != nil {
  6. return err
  7. }
  8. newInfoUser := new(interfaces.User)
  9. err = cc.Bind(newInfoUser)
  10. if err != nil {
  11. return err
  12. }
  13. db, err := cc.ConnectDB()
  14. if err != nil {
  15. return err
  16. }
  17. err = db.AutoMigrate(&models.User{})
  18. if err != nil {
  19. return err
  20. }
  21. dbUser := new(models.User)
  22. r := db.First(dbUser, userId.Id)
  23. if r.Error != nil {
  24. return cc.NoContent(http.StatusNotFound)
  25. }
  26. // 部分更新
  27. return cc.JSON(200, "")
  28. }

我可以测试每个字段是否为空,如果不为空,则更新字段,但这将导致重复的代码,我希望以一种通用的方式来实现。

期望的行为:

获取一个用户

  1. {
  2. "username": "test",
  3. "email": "test@gmail.com",
  4. "password": "password"
  5. }

并调用更新函数,传入以下请求体

  1. {
  2. "username": "test2"
  3. }

将其绑定到用户结构将创建以下对象

  1. {
  2. "username": "test2",
  3. "email": "",
  4. "password": ""
  5. }

我希望用户在更新后如下所示

  1. {
  2. "username": "test2",
  3. "email": "test@gmail.com",
  4. "password": "password"
  5. }
英文:

I got a user interface, user model and user id structures

  1. type UserId struct {
  2. Id int64 `param:"id" json:"id"`
  3. }
  4. type User struct {
  5. Email string `json:"email"`
  6. Password string `json:"password"`
  7. Username string `json:"username"`
  8. CreatedAt time.Time `json:"created_at"`
  9. UpdatedAt time.Time `json:"updated_at"`
  10. }
  11. type User struct {
  12. gorm.Model
  13. ID int64 `gorm:"primary_key"`
  14. Email string `gorm:"type:varchar(128);unique;not null"`
  15. Username string `gorm:"type:varchar(64);unique;not null"`
  16. Password string `gorm:"type:varchar(64);not null"`
  17. }

I'v got a function to update a user

  1. func updateUser(c echo.Context) error {
  2. cc := c.(*myproject.ConfigContext)
  3. userId := new(interfaces.UserId)
  4. err := cc.Bind(userId)
  5. if err != nil {
  6. return err
  7. }
  8. newInfoUser := new(interfaces.User)
  9. err = cc.Bind(newInfoUser)
  10. if err != nil {
  11. return err
  12. }
  13. db, err := cc.ConnectDB()
  14. if err != nil {
  15. return err
  16. }
  17. err = db.AutoMigrate(&models.User{})
  18. if err != nil {
  19. return err
  20. }
  21. dbUser := new(models.User)
  22. r := db.First(dbUser, userId.Id)
  23. if r.Error != nil {
  24. return cc.NoContent(http.StatusNotFound)
  25. }
  26. // the partial update
  27. return cc.JSON(200, "")
  28. }

I could test if newInfoUser is empty for each fields and update if it not but that will be replicate code and I would like to do it in a general way.

behavior wanted:

got a user

  1. {
  2. "username": "test",
  3. "email": "test@gmail.com",
  4. "password": "password"
  5. }

and call update with a body

  1. {
  2. "username": "test2"
  3. }

bind it to user structure will create

  1. {
  2. "username": "test2",
  3. "email": "",
  4. "password": ""
  5. }

and I would like user to be updated in

  1. {
  2. "username": "test2",
  3. "email": "test@gmail.com",
  4. "password": "password"
  5. }

答案1

得分: 0

我找到了一个链接 https://willnorris.com/2014/05/go-rest-apis-and-pointers/,其中展示了omitempty标签的用法。

(我意识到我犯了一个错误,不能绑定两次相同的上下文)

  1. type UserId struct {
  2. Id int64 `param:"id" json:"id"`
  3. }
  4. type User struct {
  5. Email string `json:"email,omitempty"`
  6. Password string `json:"password,omitempty"`
  7. Username string `json:"username,omitempty"`
  8. // CreatedAt time.Time `json:"created_at,omitempty"`
  9. // UpdatedAt time.Time `json:"updated_at,omitempty"`
  10. }
  11. type User struct {
  12. gorm.Model
  13. ID int64 `gorm:"primary_key"`
  14. Email string `gorm:"type:varchar(128);unique;not null"`
  15. Username string `gorm:"type:varchar(64);unique;not null"`
  16. Password string `gorm:"type:varchar(64);not null"`
  17. }
  1. func updateUser(c echo.Context) error {
  2. cc := c.(*myproject.ConfigContext)
  3. var err error
  4. userId := new(interfaces.UserId)
  5. userId.Id, err = strconv.ParseInt(cc.Param("id"), 10, 64)
  6. if err != nil {
  7. return err
  8. }
  9. newInfoUser := new(interfaces.User)
  10. err = cc.Bind(newInfoUser)
  11. if err != nil {
  12. return err
  13. }
  14. db, err := cc.ConnectDB()
  15. if err != nil {
  16. return err
  17. }
  18. err = db.AutoMigrate(&models.User{})
  19. if err != nil {
  20. return err
  21. }
  22. r := db.Model(&models.User{}).Where("id = ?", userId.Id).Updates(newInfoUser)
  23. if r.Error != nil {
  24. return cc.NoContent(http.StatusNotFound)
  25. }
  26. return cc.JSON(200, "")
  27. }

但我想知道为什么它不能与CreatedAt和UpdatedAt字段一起工作。

英文:

I find https://willnorris.com/2014/05/go-rest-apis-and-pointers/ which show the omitempty tag

(I realized I did a mistake, can't bind 2 times the same context)

  1. type UserId struct {
  2. Id int64 `param:"id" json:"id"`
  3. }
  4. type User struct {
  5. Email string `json:"email,omitempty"`
  6. Password string `json:"password,omitempty"`
  7. Username string `json:"username,omitempty"`
  8. // CreatedAt time.Time `json:"created_at,omitempty"`
  9. // UpdatedAt time.Time `json:"updated_at,omitempty"`
  10. }
  11. type User struct {
  12. gorm.Model
  13. ID int64 `gorm:"primary_key"`
  14. Email string `gorm:"type:varchar(128);unique;not null"`
  15. Username string `gorm:"type:varchar(64);unique;not null"`
  16. Password string `gorm:"type:varchar(64);not null"`
  17. }
  1. func updateUser(c echo.Context) error {
  2. cc := c.(*myproject.ConfigContext)
  3. var err error
  4. userId := new(interfaces.UserId)
  5. userId.Id, err = strconv.ParseInt(cc.Param("id"), 10, 64)
  6. if err != nil {
  7. return err
  8. }
  9. newInfoUser := new(interfaces.User)
  10. err = cc.Bind(newInfoUser)
  11. if err != nil {
  12. return err
  13. }
  14. db, err := cc.ConnectDB()
  15. if err != nil {
  16. return err
  17. }
  18. err = db.AutoMigrate(&models.User{})
  19. if err != nil {
  20. return err
  21. }
  22. r := db.Model(&models.User{}).Where("id = ?", userId.Id).Updates(newInfoUser)
  23. if r.Error != nil {
  24. return cc.NoContent(http.StatusNotFound)
  25. }
  26. return cc.JSON(200, "")
  27. }

but I wonder why it is not working with createAt and updateAt fields

huangapple
  • 本文由 发表于 2022年8月11日 23:37:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/73323435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定