免责声明:点击此处
我的用户结构为
type User struct {
ID uint32 `json:"id"`
FirstName string `json:"firstName" binding:"required"`
LastName string `json:"lastName"`
Email string `json:"email" binding:"required,email,uniqueModelValue=users email"`
Active bool `json:"active"`
Password string `json:"password,omitempty" binding:"required,gte=8"`
UserType string `json:"userType" binding:"oneof=admin backoffice principal staff parent student"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
/POST /users
处理器
func Create(ctx *gin.Context) {
user := models.User{}
//validate
if err := ctx.ShouldBind(&user); err != nil {
response.Error(ctx, err)
return
}
db, _ := database.GetDB()
db.Create(&user)
// removing password from the response
user.Password = ""
response.Success(ctx, user)
}
我想使用同一个结构创建一个更新处理程序,有什么方法可以使用同一结构执行吗?
请注意,struct在许多字段firstName,email
等上都需要绑定。在更新时,我可能不会通过这些字段
我想出了类似的东西
/PUT /users/
处理器
func Update(ctx *gin.Context) {
userID := ctx.Param("userId")
user := models.User{}
db, _ := database.GetDB()
if err := db.First(&user, userID).Error; err != nil {
response.Error(ctx, err)
return
}
updateUser := models.User{}
if err := ctx.BindJSON(&updateUser); err != nil {
response.Error(ctx, err)
}
//fmt.Printf("%v", updateUser)
db.Model(&user).Updates(updateUser)
response.Success(ctx, user)
}
这显然是由于缺少所需的验证而失败的,如果我尝试更新,比如说,只更新lastName
对于这种情况,您可以尝试绑定到刚刚从数据库中提取的User
结构,如下所示:
func Update(ctx *gin.Context) {
userID := ctx.Param("userId")
user := models.User{}
db, _ := database.GetDB()
if err := db.First(&user, userID).Error; err != nil {
response.Error(ctx, err)
return
}
if err := ctx.BindJSON(&user); err != nil {
response.Error(ctx, err)
}
db.Model(&user).Updates(user)
response.Success(ctx, user)
}
这可能会起作用,因为旧值+更改(由BindJSON
写入结构(可能能够通过验证。
一般来说,这种模式在围棋中不会帮你太久。
将同一结构用于两种不同的目的:实体模型的表示和API中与该模型相关的消息的表示,迟早会给您带来麻烦。这些往往略有不同,例如,您可能最终拥有仅在内部公开的字段,或者,正如您所遇到的,您拥有的验证对所有用例都没有意义。
对于这个问题,帮助您的是创建一个新的结构来表示更新用户消息:
package messages
type UpdateUser struct {
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
... fields that are updatable with appropriate validation tags
}
func (u *UpdateUser) ToModel() *model.User {
return &model.User{
FirstName: u.FirstName,
LastName: u.LastName,
...
}
}
然后使用它来验证您的请求模型,然后将其转换为更新的model.User
:
func Update(ctx *gin.Context) {
userID := ctx.Param("userId")
user := models.User{}
db, _ := database.GetDB()
if err := db.First(&user, userID).Error; err != nil {
response.Error(ctx, err)
return
}
updateUser := messages.UpdateUser{}
if err := ctx.BindJSON(&updateUser); err != nil {
response.Error(ctx, err)
}
//fmt.Printf("%v", updateUser)
db.Model(&user).Updates(updateUser.ToModel())
response.Success(ctx, user)
}
如果在项目中使用类似ORM的Gorm,建议对请求和响应使用视图模型结构。因为数据库表的结构与rest api模型的结构大多不同。使用视图模型结构可以更容易地进行数据绑定和验证。