技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2

技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2

相关文章:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-1.工具和本地环境
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-2.启动项目
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-3.接收json数据
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-4.连接mongodb数据库
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-5.跨域并跨域传输数据
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-6.GO语言做通用CRUD接口-1
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-8.模型的关联——无限层级分类
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-9.管理员及登录注册功能的实现
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-10.生产环境编译

1.制作分类功能的列表页

CategoryList.vue:

<template>
    <div>
        <h1>分类列表h1>
        <el-table :data="items">
            <el-table-column prop="_id" label="ID" width="220">
            el-table-column>
            <el-table-column prop="parent.name" label="上级分类">
            el-table-column>
            <el-table-column prop="name" label="分类名称">
            el-table-column>
            <el-table-column
            fixed="right"
            label="操作"
            width="100">
                <template slot-scope="scope">
                    <el-button type="text" size="small" @click="$router.push('/categories/edit/' + scope.row._id)">编辑el-button>
                    <el-button @click="remove(scope.row)" type="text" size="small">删除el-button>
                template>
            el-table-column>
        el-table>
    div>
template>
<script>
export default {
    data() {
        return {
            items: []
        }
    },
    methods: {
        async fetch(){
            const res = await this.$http.get('rest/categories')
            this.items = res.data
        },
        remove(row){
            this.$confirm('是否确定要删除分类"' + row.name + '"?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(async () => {
                // 要想使用await,函数必须使用async
                // await异步执行,待调用接口获取数据完成后再将值传给res,进行下一步操作
                const res = await this.$http.delete('rest/categories/' + row._id)
                this.$message({
                    type: 'success',
                    message: '删除成功!'
                });
                if(res.status == 200){
                    // 接口调用成功后,刷新页面
                    this.fetch()
                }
            }).catch(() => {
                this.$message({
                    type: 'info',
                    message: '已取消删除'
                });          
            });
        }
    },
    created() {
        this.fetch()
    }
}
script>

解释:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第1张图片
在首页导航中引入该页面:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第2张图片
在路由页面引入组件和路由:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第3张图片
保存进入admin端页面查看效果:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第4张图片

2.CRUD接口中的查找数据

可以看到上方页面已经显示成功,但是里边的数据并没有呈现出来,是因为查询数据接口还没有完善,下面针对查找信息接口进行完善:
(1)接口地址:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第5张图片
接口地址正确,没问题。
(2)接口函数:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第6张图片
目前接口函数还是最开始我们学习接口路由时,测试使用user表的数据模型,与现在接口不匹配,所以我们要整改一下:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第7张图片
此时,编译测试,没问题。
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第8张图片
在admin端页面进入分类列表页面:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第9张图片
接口调用成功,但没有成功后的数据。检查原因:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第10张图片
我们的接口传值为categories,但是表名和参数判断为category,所以把接口传递的参数改为category即可:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第11张图片
保存刷新admin端,测试还是不行,原来是因为没有将获取的数据以json格式返回:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第12张图片
重新编译进行测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第13张图片
查询所有数据成功,没问题。

3.CRUD接口中的删除数据

检查接口:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第14张图片
优化删除接口:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第15张图片
由于删除字段的命令相同,不需要用到模型,所以免去了if-else判断模型字段的过程。
编译运行,测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第16张图片
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第17张图片
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第18张图片
此时可以看到过程都没问题,但是我们想删除的字段并没有删除成功,查看运行结果:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第19张图片
原因是web端中id值没有传成功,也就是没有找到该条信息中的id。
同时我也意识到之前的查询接口中,也没有成功查询到id字段:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第20张图片
经短时间查找原因,发现一个大BUG,虽然我们插入字段的过程中mongodb会自动生成_id,所以不需要在模型中定义id字段,但我们查询数据是需要通过模型进行查询的:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第21张图片
于是我们需要在模型中添加一个id字段:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第22张图片
保存编译,刷新页面测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第23张图片
_id字段就查询出来了,同时上方ID也显示。
此时再测试删除字段:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第24张图片
旭,居然还在:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第25张图片
检查问题!查看手册!!百度!!!!
原因是数据库中的id是个bson格式,而我们传来的id是string字符串格式,所以使用id字段需要把它变成bson格式:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第26张图片
我就不信,这次一定可以!
编译执行测试:
还!是!不!可!以!!!
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,接着查:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第27张图片
hehe,居然又是传参错误,改成category。
在这里插入图片描述
测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第28张图片
成功了,可以,研究一下午终于成了。

4.CRUD接口中的单条查询和修改数据

我们修改分类功能复用添加分类功能的组件categorySet.vue组件:
在这里插入图片描述
修改组件:

<template>
    <div>
        <h1>创建分类h1>
        <el-form label-width="80px" style="margin-top:20px;" @submit.native.prevent="save">
            
            <el-form-item label="分类名">
                <el-input v-model="model.name">el-input>
                
            el-form-item>
            <el-form-item>
                <el-button type="primary" native-type="submit">保存el-button>
            el-form-item>
        el-form>
    div>
template>
<script>
export default {
    data(){
        return {
            model: {}
        }
    },
    methods: {
        // 使用async..await异步请求方法
        async save(){
            let res
            // 这里放axios方法,用来提交数据
            if(this.id){
                // 传id值,表明修改哪一条数据
                res = await this.$http.put('rest/categories/' + this.id, this.model)
            }else{
                res = await this.$http.post('rest/categories', this.model)
            }
            this.$router.push('/categories/list')
            // 提示信息,使用vue中自带的$message实例
            this.$message({
                type: 'success',
                message: '保存成功'
            })
        },
        async fetch(){
            const res = await this.$http.get('rest/categories/' + this.id)
            this.model = res.data
        },
    },
    created(){
        this.id && this.fetch()
    }
}
script>

技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第29张图片
修改完成,测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第30张图片
说res没有被使用,小bug不足为虑,在下边console一个即可:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第31张图片
再测试,新建分类:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第32张图片
列表页面点击编辑,暂时没有页面生成:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第33张图片
应该是无法获取id,继续修改,给CategorySet.vue中添加props:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第34张图片
同时在admin/index.js路由文件中添加修改数据路由:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第35张图片
最后,在编辑按钮路由地址处将create改成edit:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第36张图片
保存,重新点击编辑:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第37张图片
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第38张图片
页面出现,说明组件复用成功,但是数据没有查询成功。
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第39张图片
(1)CRUD根据id查询数据接口:
第一步,还是改前端接口调用处的categories:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第40张图片
第二步,修改根据id查询数据接口:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第41张图片
编译启动,测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第42张图片
成功,没问题。
(2)CRUD修改数据 接口:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第43张图片
调用接口地址没问题,调整修改数据接口:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第44张图片
编译启动,测试,将123改为“node.js”:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第45张图片
接口调用成功,但数据没有成功修改:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第46张图片
经过二次测试,发现form没有值:
在这里插入图片描述
进一步搞懂,根据模型为form赋值的方法需要有.bind()方法进行数据的合并,同时&form已经是json格式,不需要使用bson.M方法,修改如下:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第47张图片
此时,重新编译启动,修改测试:
技能学习:学习使用golang(gin框架) + vue.js,开发前端全栈网站-7.GO语言做通用CRUD接口-2_第48张图片
成功。
到此restful风格的CRUD接口全部完成,下面将全部后端接口贴给大家:

package db

import(
	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"net/http"
	"strings"
	// "fmt"
	
	// 引入模型
	"server/models"
)

// 插入数据
func insert(ctx *gin.Context){

	// 解析api参数
	resource := ctx.Param("resource")

	// 连接mongodb服务
	url := "mongodb://127.0.0.1"
	// 设置数据库一致性模式
	// 连接数据库操作,该操作赋值给session
	// err值必写,用于错误处理
	session, err := mgo.Dial(url)
	// 后边程序执行的err与go程序比对,若有错误则返回错误内容
	if err != nil { 
		panic(err) 
	}else{
		// 若没有错误,则在页面返回字符串,显示插入成功
		ctx.String(http.StatusOK, "插入成功")
	}
	// defer用法大家自行百度,我解释不清
	defer session.Close()

	// 设置数据库一致性模式,就当作打开数据库
	session.SetMode(mgo.Monotonic, true)
	// 找到某数据库下的某数据表
	c := session.DB("db_go").C(resource)
	// 以上为连接数据库
	
	if resource == "user" {
		type modelName models.User
		// 使用user数据模型
		var form modelName
	
		// 如果传值格式不符合上方定义的结构,则返回错误信息
		if err := ctx.Bind(&form); err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		// 此时&form就继承了上方定义的结构格式
		// 插入数据,并将insert状态传值给err
		err = c.Insert(&form)
	} else if resource == "category" {
		type modelName models.Category
		// 使用user数据模型
		var form modelName
	
		// 如果传值格式不符合上方定义的结构,则返回错误信息
		if err := ctx.Bind(&form); err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		// 此时&form就继承了上方定义的结构格式
		// 插入数据,并将insert状态传值给err
		err = c.Insert(&form)
	}
	// ctx.String(http.StatusOK, fmt.Sprintf(resource))
}

// 查询数据
func find(ctx *gin.Context){

	// 解析api参数
	resource := ctx.Param("resource")
	id := ctx.Param("id")
	// 传来的id值为"/id",我们要把"/"截去
	id = strings.Trim(id, "/")
	// 将id转化为bson.ObjectId格式
	var _id bson.ObjectId
	_id = bson.ObjectIdHex(id)

	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C(resource)
	// 以上为数据库连接

	if resource == "user" {
		type modelName models.User
	
		modelNamer := modelName{}
		// 查找数据
		err = c.Find(bson.M{"_id": _id}).One(&modelNamer)
		ctx.JSON(http.StatusOK, modelNamer)
	} else if resource == "category" {
		type modelName models.Category

		modelNamer := modelName{}
		// 查找数据
		err = c.Find(bson.M{"_id": _id}).One(&modelNamer)
		ctx.JSON(http.StatusOK, modelNamer)
	}

	
}

// 查询全部数据
func findAll(ctx *gin.Context){

	// 解析api参数
	resource := ctx.Param("resource")

	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C(resource)

	if resource == "user" {
		// 使用user数据模型
		type modelName models.User
		// 查找10条数据
		modelNames := make([]modelName, 10)
	
		// 查找全部
		err = c.Find(nil).All(&modelNames)

		// 返回数据
		ctx.JSON(http.StatusOK, modelNames)
	} else if resource == "category" {
		// 使用user数据模型
		type modelName models.Category
		// 查找10条数据
		modelNames := make([]modelName, 10)
	
		// 查找全部
		err = c.Find(nil).All(&modelNames)
		
		// 返回数据
		ctx.JSON(http.StatusOK, modelNames)
	}
}

// 删除数据
func delete(ctx *gin.Context){

	// 解析api参数
	resource := ctx.Param("resource")
	id := ctx.Param("id")
	// 传来的id值为"/id",我们要把"/"截去
	id = strings.Trim(id, "/")
	// 将id转化为bson.ObjectId格式
	var _id bson.ObjectId
	_id = bson.ObjectIdHex(id)

	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}else{
		ctx.String(http.StatusOK, id)
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C(resource)

	// 根据获取到的id删除内容
	err = c.Remove(bson.M{"_id": _id})
	
}

// 修改数据
func update(ctx *gin.Context){

	// 解析api参数
	resource := ctx.Param("resource")
	id := ctx.Param("id")
	// 传来的id值为"/id",我们要把"/"截去
	id = strings.Trim(id, "/")
	// 将id转化为bson.ObjectId格式
	var _id bson.ObjectId
	_id = bson.ObjectIdHex(id)

	url := "mongodb://127.0.0.1"
	session, err := mgo.Dial(url)
	if err != nil { 
		panic(err) 
	}else{
		ctx.String(http.StatusOK, "修改成功")
	}
	defer session.Close()

	session.SetMode(mgo.Monotonic, true)
	c := session.DB("db_go").C(resource)
	// 以上为连接数据库
	
	if resource == "user" {
		type modelName models.User
		// 使用user数据模型
		var form modelName
		// 合并数据,如果传值格式不符合上方定义的结构,则返回错误信息
		if err := ctx.Bind(&form); err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
	
		// 如果传值格式不符合上方定义的结构,则返回错误信息
		err = c.Update(bson.M{"_id": _id}, &form)
		ctx.JSON(http.StatusOK, &form)
	} else if resource == "category" {
		type modelName models.Category
		// 使用user数据模型
		var form modelName
		// 合并数据,如果传值格式不符合上方定义的结构,则返回错误信息
		if err := ctx.Bind(&form); err != nil {
			ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
	
		// 如果传值格式不符合上方定义的结构,则返回错误信息
		err = c.Update(bson.M{"_id": _id}, &form)
		ctx.JSON(http.StatusOK, &form)
	}
	
}

// 处理跨域请求,将跨域请求函数作为中间件处理
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
 
		c.Header("Access-Control-Allow-Origin", "*") // 允许访问所有域,可以换成具体url,注意仅具体url才能带cookie信息
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token") //header的类型
		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") //允许请求方法
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type") //返回数据格式
		c.Header("Access-Control-Allow-Credentials", "true") //设置为true,允许ajax异步请求带cookie信息
 
		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

// 配置路由
func Main(e *gin.Engine)  {
	// 全局使用中间件
	e.Use(Cors())
	// 定义路由,调用接口函数
	// 增
	e.POST("/admin/api/rest/:resource", insert)
	// 删
	e.DELETE("/admin/api/rest/:resource/*id", delete)
	// 改
	e.PUT("/admin/api/rest/:resource/*id", update)
	// 查
	e.GET("/admin/api/rest/:resource", findAll)
	// 根据id查某数据
	e.GET("/admin/api/rest/:resource/*id", find)
}

大家学习过程有任何疑问可以留言,我研究好后进行回复。
下篇文章我们开始研究mongodb数据库特有的关联方法(无限级分类)。

更多设计、功能的学习经验,大家也可以去我的公众号查看!

————
在这里插入图片描述

你可能感兴趣的:(网站开发,vue.js,golang,go,vue.js,restful,mongodb,gin框架)