目录
知识回顾
python 知识点
- 路由正则匹配
path('check/username/<str:username>/', CheckUsername.as_view())
- 分组命名匹配
In [2]: import re
In [3]: a = re.match(r'[a-zA-Z]*(?P<num>\d+)[a-zA-Z]*$', 'sad131231dasda')
In [4]: a.group('num')
Out[4]: '131231'
- 模型类查询
今日讲解
用户注册
用户注册页面效果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xtlHvHnB-1643988983822)(images/image-20210110115947667.png)]
功能
注册逻辑
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-18XNr5Fb-1643988983823)(images/image-20210110130946870.png)]
- 通过方法,生成页面的图片验证码,方法需要两种触发方式: 自动执行,点击执行
- 获取输入的用户名
- 利用正则校验用户名的合法性
- 当用户名正则校验通过,向 后端 发送请求,校验 用户名是否重复
- 获取密码
- 利用正则校验密码的合法性
- 获取确认密码
- 校验 确认密码和密码 是否一致
- 获取手机号
- 利用正则校验手机号的合法性
- 当手机号正则校验通过,向 后端 发送请求,校验手机号是否重复
- 获取用户输入的验证码
- 校验验证码是否存在
- 校验是否选择复选框
- 点击注册按钮,将信息提交到后端
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VX2BF3SE-1643988983823)(images/image-20210305161043029.png)]
用户表设计
用户表: 用户名、密码、手机号、邮箱
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
mobile = models.CharField(max_length=11, verbose_name='手机号')
class Meta:
db_table = 'tb_user'
verbose_name = '用户'
verbose_name_plural = verbose_name
def __str__(self):
return self.username
# 指定用户模型类
AUTH_USER_MODEL = 'user.User' # app名.用户名模型类名, 不是固定的
用户模型类完成之后,需要先 迁移生成表,后运行项目
用户名重复性校验
API设计
# 用户名传递问题??
GET check/username/xxxx/
django
- 先通过路由匹配获取 路径中的参数: 用户名
- 在视图中,根据用户名,进行查询,得到对应的用户数量
- 返回结果
视图
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *
# Create your views here.
class CheckUsernameAPIView(APIView):
def get(self, request, username):
"""
1. 用户名格式不正确,返回 404
2. 用户名格式正确,用户名重复,返回 400
3. 用户名格式正确,也不重复,返回 200
"""
# 1. 根据用户名查询用户数量
n = User.objects.filter(username=username).count()
# 2. 返回结果
if n == 0:
return Response({'msg': 'OK'})
else:
return Response({'msg': 'FAIL'}, status=400)
路由
from django.urls import path, re_path
from user.views import *
urlpatterns = [
re_path(r'check/username/(?P<username>[a-zA-Z]\w{5,19})/', CheckUsernameAPIView.as_view())
]
创建超级用户,只是为了接下来测试 用户名是否重复
$ python manage.py createsuperuser # 创建超级用户
Username: admin1 # 输入用户名
Email address: lsf@163.com # 输入邮箱
Password: # 输入密码,看不到
Password (again): # 输入确认密码,看不到,必须和上一个一致
This password is too short. It must contain at least 8 characters. # 密码太常见,不安全
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: y # 是否继续使用该密码
Superuser created successfully.
Vue
想要在Vue中使用模板,并保留样式
- 先将模板中的标签元素 复制到 Vue组件的
template
- 清除 app.vue中 默认的 样式
- 在
main.js
导入 css样式文件
用户名校验
- 用户在文本框输入用户名
- 使用v-mdoel指令 获取 用户名
- 在用户输入完成之后,触发 失焦事件(
blur
), 执行 校验 用户名的 方法 - 在方法中
- 先使用js的正则校验 用户名, 如果有问题, 首先将 标志
username_flag
设置true, 并且将 错误信息username_err
设置 为输入 6-20字符的用户名
, 直接结束 - 如果第一步没问题,需要将用户名 发送给django, 做重复性 校验, 如果返回的状态码为400, 说明用户名重复, 需要 标志
username_flag
设置true, 并且将 错误信息username_err
设置 为用户名已注册
- 先使用js的正则校验 用户名, 如果有问题, 首先将 标志
<li>
<label>用户名:</label>
<!-- blur:属于失焦事件 -->
<input type="text" name="user_name" id="user_name" v-model="username"
@blur="check_username">
<span class="error_tip" v-show="username_flag">{{ username_err }}</span>
</li>
export default {
name: "Register",
data() {
return {
username_flag: false, // 标志 是否显示 错误信息, false不显示错误信息, true显示
username: '', // 用户输入的 用户名
username_err: '' // 显示的错误信息
}
},
methods: {
check_username() {
// 1. js判断 用户名是否合法
let reg = /^[a-zA-Z]\w{5,19}$/
if (reg.test(this.username) === false) {
this.username_flag = true // 说明用户名的正则匹配失败。需要显示错误信息
this.username_err = '请输入6-20个字符的用户名'
return
} else {
this.username_flag = false
}
// 2. 当js判断用户名合法,再将用户名发送到django,判断用户名是否重复
console.log(this.username)
this.$axios.get('check/username/' + this.username + '/')
.then(resp => {
console.log(resp.data)
this.username_flag = false // 不显示错误信息
})
.catch(err => {
console.log(err.response.data)
this.username_flag = true // 需要显示错误信息
this.username_err = '用户名已注册'
})
}
}
}
</script>
手机号重复性校验
API设计
# 用户名传递问题??
GET check/mobile/xxxx/
django
视图
class CheckMobileAPIView(APIView):
def get(self, request, mobile):
"""
1. 手机号格式不正确,返回 404
2. 手机号重复,返回 400
3. 手机号格式正确,也不重复,返回 200
"""
# 1. 根据用户名查询用户数量
n = User.objects.filter(mobile=mobile).count()
# 2. 返回结果
if n == 0:
return Response({'msg': 'OK'})
else:
return Response({'msg': 'FAIL'}, status=400)
路由
from django.urls import path, re_path
from user.views import *
urlpatterns = [
re_path(r'check/mobile/(?P<mobile>1[3-9]\d{9})/', CheckMobileAPIView.as_view())
]
Vue
- 用户在文本框输入手机号
- 使用v-mdoel指令 获取 手机号
- 在用户输入完成之后,触发 失焦事件(
blur
), 执行 校验 手机号的 方法 - 在方法中
- 先使用js的正则校验 手机号, 如果有问题, 首先将 标志
mobile_flag
设置true, 并且将 错误信息mobile_err
设置 为请输入11位的手机号
, 直接结束 - 如果第一步没问题,需要将手机号 发送给django, 做重复性 校验, 如果返回的状态码为400, 说明手机号重复, 需要 标志
mobile_flag
设置true, 并且将 错误信息mobile_err
设置 为手机号已注册
- 先使用js的正则校验 手机号, 如果有问题, 首先将 标志
<li>
<label>手机号:</label>
<input type="text" name="phone" id="phone" v-model="mobile" @blur="check_mobile">
<span class="error_tip" v-show="mobile_flag">{{ mobile_err }}</span>
</li>
<script>
export default {
name: "Register",
data() {
return {
mobile_flag: false, // 标志 是否显示 手机号的错误信息, false不显示错误信息, true显示
mobile: '', // 代表 用户输入的 手机号
mobile_err: '', // 显示手机号的错误信息
}
},
methods: {
check_mobile() {
// 1. js校验手机号
let reg = /^1[3-9]\d{9}$/
if (reg.test(this.mobile) === false) {
this.mobile_flag = true // 设置标志位true,显示错误信息
this.mobile_err = '请输入11位的手机号'
return
} else {
this.mobile_flag = false
}
// 2. 将手机号发送给django
this.$axios.get('check/mobile/' + this.mobile + '/')
.then(resp => {
this.mobile_flag = false // 校验成功,不显示错误信息
})
.catch(err => {
this.mobile_flag = true // 校验失败,显示错误信息
this.mobile_err = '手机号已注册'
})
}
}
}
</script>
作业
- 创建django项目,实现跨域配置
- 创建 Vue项目,实现 axios默认配置
- 实现 用户名测试接口,实现 用户名重复性校验和合法性校验(由字母、数字组成,5-20位)
- 实现 手机号 测试接口, 实现 手机号合法性校验和重复性校验
- 实现 邮箱 测试接口
- 实现 邮箱合法性校验: 用户名是字母、数字组成,5-20位,邮箱只能是 sina、qq、163邮箱, 如
lixianfeng@163.com
- 实现邮箱重复性校验
- 实现 邮箱合法性校验: 用户名是字母、数字组成,5-20位,邮箱只能是 sina、qq、163邮箱, 如
- 实现用户注册页面:用户名、手机号、邮箱
- 当用户输入完成 用户名之后,立即测试 该用户名是否合法以及是否重复
- 当用户输入完成 手机号之后,立即测试 该手机号是否合法以及是否重复
- 当用户输入完成 邮箱 之后,立即测试 该邮箱是否合法以及是否重复
考试强化
以下所有功能使用 drf + Vue实现
- 创建goods 应用
- 创建模型类
- 品牌:品牌名
- 商品:商品名、价格、所属品牌(外键)
- 实现品牌的添加
- 实现商品的添加,外键使用下拉框
- 首页展示 所有品牌
- 点击品牌,跳转到 品牌对应的 商品列表页面
- 在商品列表页面展示该品牌的所有商品
- 点击商品,跳转到商品详情页面,显示商品的详细信息