10-blog-创建文章

135 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情

前言:

创建文章基本思路:

00 登录验证token
01 获取用户提交的数据(body中)null?empty?
02 数据验证:登录用户存在数据库中(验证email)
03 生成别名唯一slug
04 存储文章
05 存储标签:文章和标签关系存储/新的标签存储
06 返回文章:slug content description title email
6.1 获取文章、标签、作者
6.2 文章信息进行处理
6.3 响应数据

正文

在路由处使验证token是否存在:

const express = require("express")
const router = express.Router()
const authMiddleware = require("../middleware/authMiddleware")
const {createArticle} = require("../controller/article")

router.post('/',authMiddleware,createArticle)

module.exports=router

验证数据,是否为null?是否符合标准?

const validator = require("validator")
// 创建文章---数据校验
const validateCreateArticle = (title,description,body)=>{
    console.log("----------");
    let error={}
    if(validator.isEmpty(title)){
        error.username="title不能为空"
    }
    if(validator.isEmpty(description)){
        error.password="description不能为空"
    }
    if(validator.isEmpty(body)){
        error.email="body不能为空"
    }
    let validate = Object.keys(error).length<1//true验证通过
    return {error,validate}
}

module.exports = validateCreateArticle

然后在控制器中传入从body中获取的方法

 let {error,validate} = validateCreateArticle(title,description,body)
if(!validate){
            throw new HttpException(401,"数据提交有误","title,description,body不能为空")
}

业务验证:验证作者是否存在?

const {email} = req.user;
const author = await User.findByPk(email); //去数据库中找到这一条数据
        if(!author){
            throw new HttpException(401,"作者账号不存在","author is not found")
        }

以上,完成token验证,完成提交数据的格式校验,完成用户email的验证

可以开始创建文章了,但是在创建之前要先使用一个插件用于生成slug唯一标识,作为每一篇文章的唯一标识。

npm install unique-slug

然后就可以像封装jwt一样写一个方法啦,只需要在需要时调用即可。

var uniqueSlug = require('unique-slug')

let randomSlug = ()=>{
    let slug = uniqueSlug()
    return slug;
}
module.exports=randomSlug

使用该方法创建slug,并将从body中获取到的数一并存入进article数据库中。

        let slug = randomSlug()
        let article = await Article.create({
            slug,
            title,
            description,
            body,
            UserEmail:email //该用户的email也传入方便后续使用
        })

以上完成用户创建文章并存储进数据库

还有一些逻辑要考虑:发布文章时,会增添标签,分新标签与老标签。

目的:要将这些标签一并与文章关联在一起,绑定在一起。

在之前写模块的时候将tag与model进行了多对多的关联:

 Artical.belongsToMany(Tag,{
        through:"TagList",
        uniqueKey:false,
        timestamps:false
    });
    Tag.belongsToMany(Artical,{
        through:"TagList",
        uniqueKey:false,
        timestamps:false
    });

他们之间有一个关联表叫TagList,也就是所有多对多的关系会在该表中插入数据,需要我们手动传入。

  1. 先进行校验,遍历数组,判断tag是否已经在数据库Tag中存在,如果存在那直接就创建标签与文章的关系;如果不存在,则需将该标签存入Tag数据库,再将新标签建立与文章的关系。

  2. 存储标签与文章关系?

因为是多对多的关联关系,所以打印这条数据__proto__时会发现有许多自动额外增加的方法。 其中包含user的多对多关系,评论的多对多关系,文章的多对多关系都有方法可用

image.png

我们在此场景使用addTag的方法向关联表中插入文章与tag关联数据。

 if(tags.length>0){
            //遍历每一个标签
            for (const tag of tags) {
                let existTag = await Tag.findByPk(tag)
                if(!existTag){ //如果不存在
                    //存储标签
                   let newTag = await Tag.create({
                        name:tag
                    })
                    //存储新标签和文章的关系
                   await article.addTag(newTag) //文章与tag关联数据
                }else{ //老标签直接建立关系
                   await article.addTag(existTag)
                }
            }
        }

最后

响应数据:

根据唯一标识slug获取该文章(包含返回文章对应的标签)

article = await Article.findByPk(slug,{include:Tag})

将该文章返回:

 res.status(201)
           .json({
            status:1,
            message:"文章创建成功",
            data:article.dataValues //返回文章与对应的标签
           })

结果:

每一个slug都与tag形成关联表:

image.png

新tag与旧tag不会冲突的重复增加:

image.png

后台响应数据:

image.png