英文:
Partial update a structure with echo and gorm
问题
我有一个用户界面、用户模型和用户ID结构。
type UserId struct {
Id int64 `param:"id" json:"id"`
}
type User struct {
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type User struct {
gorm.Model
ID int64 `gorm:"primary_key"`
Email string `gorm:"type:varchar(128);unique;not null"`
Username string `gorm:"type:varchar(64);unique;not null"`
Password string `gorm:"type:varchar(64);not null"`
}
我有一个更新用户的函数。
func updateUser(c echo.Context) error {
cc := c.(*myproject.ConfigContext)
userId := new(interfaces.UserId)
err := cc.Bind(userId)
if err != nil {
return err
}
newInfoUser := new(interfaces.User)
err = cc.Bind(newInfoUser)
if err != nil {
return err
}
db, err := cc.ConnectDB()
if err != nil {
return err
}
err = db.AutoMigrate(&models.User{})
if err != nil {
return err
}
dbUser := new(models.User)
r := db.First(dbUser, userId.Id)
if r.Error != nil {
return cc.NoContent(http.StatusNotFound)
}
// 部分更新
return cc.JSON(200, "")
}
我可以测试每个字段是否为空,如果不为空,则更新字段,但这将导致重复的代码,我希望以一种通用的方式来实现。
期望的行为:
获取一个用户
{
"username": "test",
"email": "test@gmail.com",
"password": "password"
}
并调用更新函数,传入以下请求体
{
"username": "test2"
}
将其绑定到用户结构将创建以下对象
{
"username": "test2",
"email": "",
"password": ""
}
我希望用户在更新后如下所示
{
"username": "test2",
"email": "test@gmail.com",
"password": "password"
}
英文:
I got a user interface, user model and user id structures
type UserId struct {
Id int64 `param:"id" json:"id"`
}
type User struct {
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type User struct {
gorm.Model
ID int64 `gorm:"primary_key"`
Email string `gorm:"type:varchar(128);unique;not null"`
Username string `gorm:"type:varchar(64);unique;not null"`
Password string `gorm:"type:varchar(64);not null"`
}
I'v got a function to update a user
func updateUser(c echo.Context) error {
cc := c.(*myproject.ConfigContext)
userId := new(interfaces.UserId)
err := cc.Bind(userId)
if err != nil {
return err
}
newInfoUser := new(interfaces.User)
err = cc.Bind(newInfoUser)
if err != nil {
return err
}
db, err := cc.ConnectDB()
if err != nil {
return err
}
err = db.AutoMigrate(&models.User{})
if err != nil {
return err
}
dbUser := new(models.User)
r := db.First(dbUser, userId.Id)
if r.Error != nil {
return cc.NoContent(http.StatusNotFound)
}
// the partial update
return cc.JSON(200, "")
}
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
{
"username": "test",
"email": "test@gmail.com",
"password": "password"
}
and call update with a body
{
"username": "test2"
}
bind it to user structure will create
{
"username": "test2",
"email": "",
"password": ""
}
and I would like user to be updated in
{
"username": "test2",
"email": "test@gmail.com",
"password": "password"
}
答案1
得分: 0
我找到了一个链接 https://willnorris.com/2014/05/go-rest-apis-and-pointers/,其中展示了omitempty
标签的用法。
(我意识到我犯了一个错误,不能绑定两次相同的上下文)
type UserId struct {
Id int64 `param:"id" json:"id"`
}
type User struct {
Email string `json:"email,omitempty"`
Password string `json:"password,omitempty"`
Username string `json:"username,omitempty"`
// CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt time.Time `json:"updated_at,omitempty"`
}
type User struct {
gorm.Model
ID int64 `gorm:"primary_key"`
Email string `gorm:"type:varchar(128);unique;not null"`
Username string `gorm:"type:varchar(64);unique;not null"`
Password string `gorm:"type:varchar(64);not null"`
}
func updateUser(c echo.Context) error {
cc := c.(*myproject.ConfigContext)
var err error
userId := new(interfaces.UserId)
userId.Id, err = strconv.ParseInt(cc.Param("id"), 10, 64)
if err != nil {
return err
}
newInfoUser := new(interfaces.User)
err = cc.Bind(newInfoUser)
if err != nil {
return err
}
db, err := cc.ConnectDB()
if err != nil {
return err
}
err = db.AutoMigrate(&models.User{})
if err != nil {
return err
}
r := db.Model(&models.User{}).Where("id = ?", userId.Id).Updates(newInfoUser)
if r.Error != nil {
return cc.NoContent(http.StatusNotFound)
}
return cc.JSON(200, "")
}
但我想知道为什么它不能与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)
type UserId struct {
Id int64 `param:"id" json:"id"`
}
type User struct {
Email string `json:"email,omitempty"`
Password string `json:"password,omitempty"`
Username string `json:"username,omitempty"`
// CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt time.Time `json:"updated_at,omitempty"`
}
type User struct {
gorm.Model
ID int64 `gorm:"primary_key"`
Email string `gorm:"type:varchar(128);unique;not null"`
Username string `gorm:"type:varchar(64);unique;not null"`
Password string `gorm:"type:varchar(64);not null"`
}
func updateUser(c echo.Context) error {
cc := c.(*myproject.ConfigContext)
var err error
userId := new(interfaces.UserId)
userId.Id, err = strconv.ParseInt(cc.Param("id"), 10, 64)
if err != nil {
return err
}
newInfoUser := new(interfaces.User)
err = cc.Bind(newInfoUser)
if err != nil {
return err
}
db, err := cc.ConnectDB()
if err != nil {
return err
}
err = db.AutoMigrate(&models.User{})
if err != nil {
return err
}
r := db.Model(&models.User{}).Where("id = ?", userId.Id).Updates(newInfoUser)
if r.Error != nil {
return cc.NoContent(http.StatusNotFound)
}
return cc.JSON(200, "")
}
but I wonder why it is not working with createAt and updateAt fields
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论