【Django开发】django美多商城项目完整开发4.0第3篇:用户部分,1. 后端接口设计【附代码文档】
本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后端接口设计: 用户部分 JWT 什么是JWT 起源 传统的session认证 用户部分 登录 1. 业务说明 2. 后端接口设计 3. 后端实现 登录 使用登录的流程 创建模型类 urllib使用说明 登录回调处理 登录 使用登录的流程 创建模型类 urllib使用说明 绑定用户身份接口 邮件与验证 学习目标: 业务说明: 技术说明: 保存邮箱并发送验证邮件 省市区地址查询 数据库建表 说明 页面静态化 注意 定时任务 安装 部分 详情页 异步任务的触发 。 后端接口设计 收货地址 使用缓存 安装 使用方法 为省市区视图添加缓存 数据库表设计 表结构 数据表结构 首页数据表结构 Docker使用 Docker简介 用户浏览历史记录 1. 保存 后端接口设计 后端实现 搜索 1. 需求分析 2. 搜索引擎原理 3. Elasticsearch 部分 业务需求分析 技术实现 数据存储设计 1. Redis保存已登录用户 商品部分 业务需求分析 技术实现 查询数据 1. 后端接口设计 部分 业务需求分析 技术实现 登录合并 修改登录视图 部分 保存 1. 后端接口设计 2. 后端实现 保存的思路 创建数据库模型类 接入 开发平台登录 沙箱环境 Xadmin 1. 安装 2. 使用 站点的全局配置 站点Model管理。 在Ubuntu中安装 2. 启动与停止 3. 镜像操作 端与自定义文件存储系统 1. 的Python客户端 安装 使用。
全套笔记资料代码移步:
感兴趣的小伙伴可以自取哦~
全套教程部分目录:
部分文件图片:
用户部分
图片验证码
1. 后端接口设计:
访问方式: GET /image_codes/(?P<image_code_id>[\w-]+)/
请求参数: 路径参数
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
image_code_id | uuid字符串 | 是 | 图片验证码编号 |
返回数据:
验证码图片
视图原型
# url('^image_codes/(?P<image_code_id>[\w-]+)/$', views.ImageCodeView.as_view()),
class ImageCodeView(APIView):
"""
图片验证码
"""
pass
2. 具体视图实现
在verifications/views.py中实现视图
class ImageCodeView(APIView):
"""
图片验证码
"""
def get(self, request, image_code_id):
"""
获取图片验证码
"""
# 生成验证码图片
text, image = captcha.generate_captcha()
redis_conn = get_redis_connection("verify_codes")
redis_conn.setex("img_%s" % image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
# 固定返回验证码图片数据,不需要REST framework框架的Response帮助我们决定返回响应数据的格式
# 所以此处直接使用Django原生的HttpResponse即可
return HttpResponse(image, content_type="images/jpg")
说明:
django-redis提供了get_redis_connection的方法,通过调用get_redis_connection方法传递redis的配置名称可获取到redis的连接对象,通过redis连接对象可以执行redis命令。
我们需要在配置文件中添加一个新的redis配置,用于存放验证码数据
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"verify_codes": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
3. 设置域名
我们现在为前端和后端分别设置两个不同的域名
位置 | 域名 |
---|---|
前端 | www.meiduo.site |
后端 | api.meiduo.site |
编辑/etc/hosts
文件,可以设置本地域名
sudo vim /etc/hosts
在文件中增加两条信息
127.0.0.1 api.meiduo.site
127.0.0.1 www.meiduo.site
windows系统中若设置本地域名,hosts文件在如下目录:
C:\Windows\System32\drivers\etc
我们在前端front_end_pc/js目录中,创建host.js文件用以为前端保存后端域名
var host = '
在所有需要访问后端接口的前端页面中都引入host.js,使用host
变量即可指代后端域名。
修改settings配置中的ALLOWED_HOSTS
一旦不再使用127.0.0.1访问Django后端,需要在配置文件中修改ALLOWED_HOSTS,增加可以访问后端的域名
ALLOWED_HOSTS = ['api.meiduo.site', '127.0.0.1', 'localhost', 'www.meiduo.site']
4. 前端Vue代码:
js/register.js
data: {
...
image_code_id: '', // 图片验证码编号
image_code_url: '', // 验证码图片路径
},
mounted: function() {
this.generate_image_code();
},
methods: {
// 生成uuid
generate_uuid: function(){
var d = new Date().getTime();
if(window.performance && typeof window.performance.now === "function"){
d += performance.now(); //use high-precision timer if available
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c =='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid;
},
// 生成一个图片验证码的编号,并设置页面中图片验证码img标签的src属性
generate_image_code: function(){
// 生成一个编号
// 严格一点的使用uuid保证编号唯一, 不是很严谨的情况下,也可以使用时间戳
this.image_code_id = this.generate_uuid();
// 设置页面中图片验证码img标签的src属性
this.image_code_url = this.host + "/image_codes/" + this.image_code_id + "/";
},
...
}
##
短信验证码
1. 业务处理流程
-
检查图片验证码
-
检查是否在60s内有发送记录
-
生成短信验证码
-
保存短信验证码与发送记录
-
发送短信
2. 后端接口设计:
访问方式: GET /sms_codes/(?P<mobile>1[3-9]\d{9})/?image_code_id=xxx&text=xxx
请求参数: 路径参数与查询字符串参数
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
mobile | str | 是 | 手机号 |
image_code_id | uuid字符串 | 是 | 图片验证码编号 |
text | str | 是 | 用户输入的图片验证码 |
返回数据: JSON
返回值 | 类型 | 是否必传 | 说明 |
---|---|---|---|
message | str | 否 | OK,发送成功 |
视图原型:
# url('^sms_codes/(?P<mobile>1[3-9]\d{9})/$', views.SMSCodeView.as_view()),
class SMSCodeView(GenericAPIView):
"""
短信验证码
传入参数:
mobile, image_code_id, text
"""
pass
3. 后端实现
在verifications/serializers.py中定义序列化器,用以校验
class ImageCodeCheckSerializer(serializers.Serializer):
"""
图片验证码校验序列化器
"""
image_code_id = serializers.UUIDField()
text = serializers.CharField(max_length=4, min_length=4)
def validate(self, attrs):
"""
校验
"""
image_code_id = attrs['image_code_id']
text = attrs['text']
# 查询真实图片验证码
redis_conn = get_redis_connection('verify_codes')
real_image_code_text = redis_conn.get('img_%s' % image_code_id)
if not real_image_code_text:
raise serializers.ValidationError('图片验证码无效')
# 删除图片验证码
try:
redis_conn.delete('img_%s' % image_code_id)
except RedisError as e:
logger.error(e)
# 比较图片验证码
real_image_code_text = real_image_code_text.decode()
if real_image_code_text.lower() != text.lower():
raise serializers.ValidationError('图片验证码错误')
# 判断是否在60s内
mobile = self.context['view'].kwargs['mobile']
send_flag = redis_conn.get("send_flag_%s" % mobile)
if send_flag:
raise serializers.ValidationError('请求次数过于频繁')
return attrs
在verifications/views.py中定义实现视图:
class SMSCodeView(GenericAPIView):
"""
短信验证码
"""
serializer_class = serializers.ImageCodeCheckSerializer
def get(self, request, mobile):
"""
创建短信验证码
"""
# 判断图片验证码, 判断是否在60s内
serializer = self.get_serializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
# 生成短信验证码
sms_code = "%06d" % random.randint(0, 999999)
# 保存短信验证码与发送记录
redis_conn = get_redis_connection('verify_codes')
pl = redis_conn.pipeline()
pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
pl.setex("send_flag_%s" % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
pl.execute()
# 发送短信验证码
sms_code_expires = str(constants.SMS_CODE_REDIS_EXPIRES // 60)
ccp = CCP()
ccp.send_template_sms(mobile, [code, expires], SMS_CODE_TEMP_ID)
return Response({"message": "OK"})
4. 前端实现
修改register.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
<html xmlns=" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>美多商城-注册</title>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<link rel="stylesheet" type="text/css" href="css/main.css">
<script type="text/javascript" src="js/host.js"></script>
<script type="text/javascript" src="js/vue-2.5.16.js"></script>
<script type="text/javascript" src="js/axios-0.18.0.min.js"></script>
</head>
<body>
<div class="register_con">
<div class="l_con fl">
<a class="reg_logo"><img src="images/logo.png"></a>
<div class="reg_slogan">商品美 · 种类多 · 欢迎光临</div>
<div class="reg_banner"></div>
</div>
<div class="r_con fr">
<div class="reg_title clearfix">
<h1>用户注册</h1>
<a href="/login.html">登录</a>
</div>
<div class="reg_form clearfix" id="app" v-cloak>
<form id="reg_form" @submit.prevent="on_submit">
<ul>
<li>
<label>用户名:</label>
<input type="text" v-model="username" @blur="check_username" name="user_name" id="user_name">
<span v-show="error_name" class="error_tip">{{ error_name_message }}</span>
</li>
<li>
<label>密码:</label>
<input type="password" v-model="passwo
- 点赞
- 收藏
- 关注作者
评论(0)