源码地址
前端地址:https://github.com/tdx1997tdx/my_tapd_frontend
后端地址:https://github.com/tdx1997tdx/my_tapd_backend
项目演示地址
http://139.198.36.243
项目介绍
飞雪随笔是基于MySql+Django+vue+elementUI开发日记管理系统,是前后端分离项目,主要功能如下:
- 登录注册登出
- 个人信息修改(包括头像修改)
- 日记社区,查看他人公开的日记
- 日记管理,对自己的日记进行删除,修改,查看
- 日记发布
- 日记回收站
以后大家想写日志可以在这上面写哟!~
数据库表结构设计
class User(models.Model):
username = models.CharField(max_length=20, unique=True)
password = models.CharField(max_length=20, null=False)
nickname = models.CharField(max_length=20)
introduction = models.CharField(max_length=500)
birthday = models.DateField(auto_now_add=True)
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
token = models.CharField(max_length=50)
fail_time = models.DateTimeField(
default=(datetime.datetime.now() + datetime.timedelta(days=3)).strftime("%Y-%m-%d %H:%M:%S"))
logo = models.CharField(max_length=100, default='getImage/admin.jpg')
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
is_public = models.IntegerField(default=1)
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
is_delete = models.IntegerField(default=0)
pv = models.IntegerField(default=0)
zan = models.IntegerField(default=0)
cai = models.IntegerField(default=0)
author = models.ForeignKey(User, on_delete=models.CASCADE)
重点功能设计
登录注册
前端拦截器
// 请求拦截器
instance.interceptors.request.use(
(config) => {
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加 了
const token = window.localStorage.getItem("token");
const loginName = localStorage.getItem("loginName");
token && (config.headers.Authorization = token);
loginName && (config.headers.loginName = loginName);
// 若请求方式为post,则将data参数转为JSON字符串
if (config.method === "post" || config.method === "put") {
config.data = JSON.stringify(config.data);
}
return config;
},
(error) =>
// 对请求错误做些什么
Promise.reject(error)
);
所有请求的请求头都带有loginName 和Authorization 字段存储当前用户名以及token
后端拦截器
class TokenMiddleware(MiddlewareMixin):
"""token验证中间件"""
uri_list = ['/api/login', '/api/regist', '/api/getImage', '/api/uploadImage']
def process_request(self, request):
is_pass = True
for i in TokenMiddleware.uri_list:
if i in request.path_info:
is_pass = False
if is_pass:
token = request.META.get("HTTP_AUTHORIZATION")
user_name = request.META.get("HTTP_LOGINNAME")
if not (token and user_name):
return get_response_json('AFAIL')
users = User.objects.filter(username=user_name)
if not users:
return get_response_json('AFAIL')
user = users[0]
if user.token != token or user.fail_time < datetime.datetime.now():
return get_response_json('AFAIL')
所有请求都经过用户名校验,如果失败,返回10002
前端一旦接收到10002请求,前端路由重定向到登录页面!
头像功能
后端开了2个接口,一个上传图片,另一个获取图片资源
class GetImage(View):
def get(self, request, uri):
path = os.path.join(BASE_DIR, 'static_file', uri)
if not os.path.exists(path):
return HttpResponse("图片资源不存在", status=404)
file = open(path, "rb")
return HttpResponse(file.read(), content_type='image/jpg')
class UploadImage(View):
def post(self, request):
file = request.FILES.get("file")
file_name = str(uuid.uuid4()) + "." + str(file).split('.')[-1]
path = os.path.join(BASE_DIR, 'static_file', file_name)
with open(path, 'wb') as f:
for content in file.chunks():
f.write(content)
return get_response_json("OK", {"path": "getImage/" + file_name})
前端代码详见Home.vue
小结
项目不难,主要体验一下全栈开发以及前后端代码工程化,可以优化的地方有把token放在redis中,减少mysql的压力。每天进步一点点,加油!