【问题标题】:Replace incoming post request data before bind with Go Gin?用Go Gin绑定之前替换传入的post请求数据?
【发布时间】:2021-10-04 07:53:55
【问题描述】:

我使用 Gorm And Go Gin 制作了一个简单的帖子 API 来将文章存储在数据库中。

当我尝试发布类别名称而不是类别 ID 时,API 出现问题,因为结构将其声明为 int32 类型

我做了一个简单的函数来获取类别的 id 而不是名称,但我不知道如何在传入的请求中注入它

文章模型

package models

import (
    "gorm.io/gorm"
)

type News struct {
    Id          int    `gorm:"primary_key;auto_increment;not_null" json:"id"`
    Category    int32  `gorm:"category" json:"category" binding:"required"`
    CountryID   int32  `gorm:"country_id" json:"country_id" binding:"required"`
    LangID      int32  `gorm:"lang_id" json:"lang_id" binding:"required"`
    SourceId    int32  `gorm:"source_id" json:"source_id" binding:"required"`
    HashtagId   int32  `gorm:"hashtag_id" json:"hashtag_id" binding:"required"`
    Title       string `gorm:"title" json:"title" binding:"required"`
    Content     string `gorm:"content" json:"content" binding:"required"`
    Description string `gorm:"description" json:"description" binding:"required"`
    Summery     string `gorm:"summery" json:"summery" binding:"required"`
    ImageUrl    string `gorm:"image_url" json:"image_url" binding:"required"`
    SourceUrl   string `gorm:"source_url" json:"source_url" binding:"required"`
    Author      string `gorm:"author" json:"author" `
}

func CreateArticle(db *gorm.DB, article *News) (err error) {
    err = db.Create(article).Error
    if err != nil {
        return err
    }
    return nil
}

类别模型

package models

import "gorm.io/gorm"

type Category struct {
    Id     int32  `gorm:"primary_key;auto_increment;not_null" json:"id"`
    Name   string `gorm:"category_name" json:"category" binding:"required"`
    Parent int32  `gorm:"parent" json:"parent"`
}

func GetCategoryByName(db *gorm.DB, category *Category, name string) (err error) {
    err = db.Where("LOWER(category_name) Like LOWER(?)", "%"+name+"%").First(category).Error
    if err != nil {
        return err
    }
    return nil
}

实现模型的新闻控制器

package controllers

import (
    "errors"
    "net/http"

    "github.com/fouad82/news-app-go/models"
    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
    "gorm.io/gorm"
)

type NewsRepo struct {
    db *gorm.DB
}

func NewArticle() *NewsRepo {
    db := models.InitDb()
    return &NewsRepo{db: db}
}

// CreateArticle Create Article
func (repository *NewsRepo) CreateArticle(c *gin.Context) {

    var Category models.Category
    if err := c.ShouldBindBodyWith(&Category, binding.JSON); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": &Category})
        return

    }
    err := models.GetCategoryByName(repository.db, &Category, Category.Name)
    if err != nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            c.AbortWithStatus(http.StatusNotFound)
            return
        }
        c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"status": "error", "error": err})
        return
    }
    var CategoryId = Category.Id
    var Article models.News
    Article.Category = CategoryId
    if err := c.ShouldBindBodyWith(&Article, binding.JSON); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": err})
        return

    }
    err = models.GetArticleByTitle(repository.db, &Article, Article.Title)
    if err == nil {
        if errors.Is(err, gorm.ErrRecordNotFound) {
            c.AbortWithStatus(http.StatusNotFound)
            return
        }

        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"status": "error", "error": "Title Created Before"})
        return
    }
    createArticle := models.CreateArticle(repository.db, &Article)
    if createArticle != nil {
        c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"status": "error", "error": createArticle})
        return
    }
    c.JSON(http.StatusOK, gin.H{"status": "ok", "result": "Article Created"})
}

在这一行中,我尝试在文章结构中注入 int 值,但它仍然收到错误,即我传递字符串值而不是 int,这是因为它仍然从请求 json 中读取,而不是从注入的参数中读取

var CategoryId = Category.Id
var Article models.News
Article.Category = CategoryId

【问题讨论】:

  • 我很难解析你的问题。请您能更准确地解释您要做什么,和/或重新提出问题吗?
  • 传入请求是字符串,我需要在添加文章之前进行db查询以获取id,然后注入此id而不是字符串
  • 不清楚。您应该尝试编写一个可重现的示例。 cat.ID 是 int32,article.catID 是 int32 所以 IDK。

标签: go go-gorm go-gin


【解决方案1】:

我相信你使用的函数超出了请求范围,所以基本上不会影响gin.Context。

我的建议是复制上下文,以便使用更改的数据对其进行修改。 Article.Category in specific.

...
    c.Copy
...

另一件事是关于函数 - 它正在评估自身 - 我建议将其从 CreateArticle 函数中排除

createArticle := models.CreateArticle(repository.db, &Article)

我还建议返回更改的结构并与请求有效负载分开使用它 - 可能您需要为此创建另一个函数:

   func (repository *NewsRepo) ChangedArticle(c *gin.Context)News{



    changedNews := News{
        Id:          0,
        Category:    0, // Here is where you change it
        CountryID:   0,
        LangID:      0,
        SourceId:    0,
        HashtagId:   0,
        Title:       "",
        Content:     "",
        Description: "",
        Summery:     "",
        ImageUrl:    "",
        SourceUrl:   "",
        Author:      "",
    }

        return changedNews

}

在你的主要功能中 - 只需使用它:

    ...
createArticle := models.ChangedArticle
    ...

我可能会遗漏一些细节,但我希望这个顶级解释会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2018-07-24
    相关资源
    最近更新 更多