这是我的第一个实战项目,前前后后开发了大致有两个多月的时间,在开发过程中我担任的是整个项目的后端部分(只有我一个人),采用的编程语言是Python,后端框架为Django,我总结了主要的知识点如下
- Django的基本使用(视图函数, 路由, settings配置, orm相关操作)
- Django的进阶知识,配合DjangoRestframework(分页器, 解析器, 序列化器, 限流器, 权限认证器, 身份认证器, 渲染器, 筛选器(不属于DRF))
- RBAC权限管理
- Linux系统基本操作
- git想关操作
- Redis, MySQL基本操作(由于有操作的封装, 要求比较低)
- Celery先关思想和操作
- PostMan等api接口测试工具
- DevOps自动化部署
1. 项目概览
1.1 需求分析
由于全国大学毕业生数量每年都在增多, 每年毕业季毕业论文的数量也水涨船高, 由于很多大学生在学校期间很少写过论文,并且对自己学校对论文格式的要求并不了解. 每年都有大部分人在论文写完后多次返工,不仅浪费时间也浪费精力.本项目就是旨在帮助毕业生们对论文进行一次检测找到格式不合理的位置,并给出改正建议.
1.2 项目模块
经过对需求的相关分析,项目大致分为一下几个模块
- Account(记录全部模块的账号,权限, 角色信息)
- BackendManage(平台后台管理系统)
- media(储存各种静态文件)
- PaperDetector(与远程论文检测API进行交互)
- Payment(积分支付相关组件)
- Stark(快速添加对数据库操作的路由)
1.3 表结构设计
使用Django的ORM系统能够方便的对数据库进行一系列的操作,故针对具体的要求,设计表结构如下
1.3.1 Account模块下对应的表结构设计
class Account(AbstractUser):
"""用户"""
avatar = models.URLField(verbose_name="用户头像", default='avatars/default.png')
invitation_code = models.CharField(verbose_name="邀请码", null=True, blank=True, max_length=20,
help_text="用于推广平台,用户注册时填写邀请码给予相应邀请人积分奖励")
real_name = models.CharField(verbose_name="真实姓名", max_length=150, null=True, blank=True, help_text="后期用于实名")
telephone = models.CharField(max_length=11, null=True, blank=True, unique=True, help_text="后期用于实名")
organization = models.CharField(verbose_name="机构名", null=True, blank=True, max_length=150, help_text="用户所属机构")
integral = models.IntegerField(verbose_name="积分", default=100, help_text="用户校验论文需要的积分,默认100")
delete = models.BooleanField(verbose_name="删除", default=False)
roles = models.ManyToManyField(verbose_name="角色", to="Role", blank=True)
OpenID = models.CharField(verbose_name="微信ID", null=True, max_length=150)
def __str__(self):
return self.username
class Permission(models.Model):
"""权限"""
title = models.CharField(verbose_name="权限名称", max_length=32)
url = models.CharField(verbose_name="权限URL正则表达式", max_length=256)
name = models.CharField(verbose_name="权限URL别名", max_length=32, unique=True)
icon = models.CharField(verbose_name="权限图标", max_length=32, null=True, blank=True)
parentPermission = models.ForeignKey(verbose_name="父权限", to="Permission", null=True, blank=True,
on_delete=models.PROTECT, help_text="非菜单权限需要一个二级菜单的父权限做默认展开和选中")
def __str__(self):
return self.title
class Role(models.Model):
"""角色"""
name = models.CharField(verbose_name="角色名称", max_length=32)
level = models.IntegerField(verbose_name="等级", default=50,
help_text="根据角色等级安排优先级,1-50划分为5档,用于建立多级反馈队列调度系统。")
permissions = models.ManyToManyField(verbose_name="角色所拥有权限", to='Permission', blank=True)
def __str__(self):
return self.name
1.3.2 PaperDetector下表结构设计
def user_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/<id>/<filename>
return f"PaperTemplate/{instance.user.username}/{filename}"
def user_directory_path2(instance, filename):
# file will be uploaded to MEDIA_ROOT/<id>/<filename>
return f"PaperVerify/Upload_paper/{instance.TaskId.user.username}/{filename}"
# Create your models here.
class PaperTemplate(models.Model):
"""论文模板库"""
filename = models.CharField(verbose_name="论文模板文件名", max_length=128, help_text="用户上传的论文模板文件名")
filepath = models.FileField(upload_to=user_directory_path, verbose_name="论文模板文件地址",
help_text="论文模板文件存放地址")
organization = models.CharField(verbose_name="机构名", max_length=20, help_text="论文模板所属机构,如:南开大学、IEEE")
date = models.DateTimeField(verbose_name="上传日期", help_text="论文模板上传日期")
isOpen = models.BooleanField(verbose_name='是否公开', help_text="公开论文模板所有人可选,私有论文模板仅限本人使用")
template = models.TextField(verbose_name="论文模板信息",
help_text="后端解析论文模板内容,按照预定义规则生成模板信息")
user = models.ForeignKey(verbose_name="用户ID", to=Account, on_delete=models.PROTECT,
help_text="论文模板上传者ID")
is_deleted = models.BooleanField(verbose_name="是否删除", default=False)
def __str__(self):
return self.filename
class TaskVerify(models.Model):
"""校验任务库"""
level = models.IntegerField(verbose_name="任务优先级", help_text="任务优先级")
user = models.ForeignKey(verbose_name="用户ID", to=Account, on_delete=models.PROTECT,
help_text="论文模板上传者ID")
Queue = models.CharField(verbose_name="校验论文队列", help_text="所属任务校验论文的顺序", max_length=300)
Processing_phase = models.CharField(max_length=12,
choices=(
("Created", u"创建"), ("Processing", u"处理中"), ("Finished", u"已经完成"),
("Failed", u"请求出错")))
isDeleted = models.BooleanField(default=False, verbose_name="是否删除")
def __str__(self):
return str(self.level)
class PaperVerify(models.Model):
""" 校验论文库 """
filename = models.CharField(verbose_name="校验论文文件名", help_text="上传论文文件名", max_length=128)
templateId = models.ForeignKey(verbose_name="论文模板ID", to="PaperTemplate", on_delete=models.PROTECT,
help_text="校验论文模板")
TaskId = models.ForeignKey(verbose_name="所属任务ID", to="TaskVerify", on_delete=models.PROTECT,
help_text="所属任务ID")
filepath = models.FileField(verbose_name="校验论文文件地址", help_text="校验论文文件存放地址",
upload_to=user_directory_path2)
date = models.DateTimeField(verbose_name="上传日期", help_text="校验论文长传日期")
checkModule = models.TextField(verbose_name="校验模块列表",
help_text="1-封面、2-声明、3-摘要、4-正文、5-参考文献、6-致谢")
checkContent = models.TextField(verbose_name="校验内容列表",
help_text="1-格式检查、2-拼写检查、3-语法检查、4-论文内容查重")
checkState = models.IntegerField(verbose_name="论文校验进度",
help_text="0-文件已存储、1-模块划分完成、2-格式提取完成、3-格式对比完成、4-拼写/语法检查完成、5-文档报告生成完毕")
formatInformation = models.TextField(verbose_name="论文格式信息")
annotationFile = models.CharField(verbose_name="批注文件地址", max_length=300)
errorReportFile = models.CharField(verbose_name="错误报告文件地址", max_length=300)
resultFolder = models.CharField(verbose_name="结果文件夹地址",
help_text="用户打包下载,直接压缩结果文件夹所有文件发送", max_length=300)
PaperID = models.CharField(verbose_name="论文ID", max_length=50)
def __str__(self):
return self.filename
1.3.3 Payment下表结构设计
class order(models.Model):
orderid = models.CharField(max_length=150, verbose_name="订单编号")
cash_fee = models.IntegerField(verbose_name="订单金额")
status = models.CharField(max_length=150, verbose_name="订单状态")
bank_type = models.CharField(max_length=150, verbose_name="支付方式")
user = models.ForeignKey(Account, on_delete=models.CASCADE, verbose_name="订单用户")
time_create = models.DateTimeField(auto_now=True, verbose_name="订单创建时间")
2. Account模块中表设计的原则:RBAC详解
2.1 RBAC介绍(借用其他博客)
2.1.1 在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限。
RBAC通过定义角色的权限,并对用户授予某个角色从而来控制用户的权限,实现了用户和权限的逻辑分离(区别于ACL模型),极大地方便了权限的管理:
User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
Role(角色):不同角色具有不同的权限
Permission(权限):访问权限
用户-角色映射:用户和角色之间的映射关系
角色-权限映射:角色和权限之间的映射
2.1.2 RBAC支持三个著名的安全原则:最小权限原则、责任分离原则和数据抽象原则
最小权限原则:RBAC可以将角色配置成其完成任务所需的最小权限集合
责任分离原则:可以通过调用相互独立互斥的角色来共同完成敏感的任务,例如要求一个计账员和财务管理员共同参与统一过账操作
数据抽象原则:可以通过权限的抽象来体现,例如财务操作用借款、存款等抽象权限,而不是使用典型的读、写、执行权限
2.2 我理解的RBAC
通俗的说,就是一个角色可以有多个权限,每个用户可以拥有多个角色,这样就方便了用户的管理
3. PaperDetector表结构设计
不难看出,采用了RBAC管理之后,用户的角色决定了其任务的优先级
4. Payment表结构设计
关系比较简单就不多解释了
5. 总结
由于项目涉及的知识点很多,我打算多写几期来总结,本期就先把表结构设计和整体的框架写完,欢迎持续关注哦!!!这期用的RBAC管理表设计,之前只在书上见过,主要问题就是ORM的增删改查,关系中的一对一,一对多,多对多的关系.