1.settings配置
# 注册
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # drf框架
'corsheaders', # 跨域 pip install cors
'users', # 注册用户子应用子应用
'goods', # 注册商品子应用
]
# 跨域
MIDDLEWARE = [
"middleware.Loginmiddleware.CheckUser",
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware', # 跨域中间件
]
# 配置数据库
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST':'localhost',
'USER':'root',
'POST':3306,
"PASSWORD":'123123',
'NAME':"h2111_p5"
}
}
# 配置时间
TIME_ZONE = 'Asia/Shanghai'
# 配置跨域相关配置项
# 注:单词不能写错
CORS_ORIGIN_WHITELIST = [ # 配置ip白名单
"http://127.0.0.1:8080",
"http://localhost:8080",
"http://127.0.0.1:8000",
"http://127.0.0.1:8866"
]
CORS_ALLOW_CREDENTIALS = True # 允许cookie
CORS_ALLOW_METHODS = ("*") # 配置允许的请求方式
CORS_ALLOW_HEADERS = ("*") # 配置允许的请求头
2.安装数据库
import pymysql
pymysql.install_as_MySQLdb()
3.路由分发
主路由
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path("user/",include("users.urls")),
path("goods/",include("goods.urls"))
]
在子应用下创建urls.py文件
from django.urls import path
from users import views
urlpatterns = [
path("check/username/<str:username>/",views.CheckUserNameView.as_view()), # 检测用户名
path("check/mobile/<str:mobile>/",views.CheckMobileView.as_view()), # 检测手机号
path("check/password/",views.CheckPasswordView.as_view()), # 检测密码
path("check/password2/",views.CheckPasswordView2.as_view()), # 检测再次输入密码
path("check/image/<str:uuid>/",views.VerImageView.as_view()), # 生成验证码
path("check/img/code/",views.CheckCodeView.as_view()), # 检测验证码
path("reg/",views.RegView.as_view()), # 注册
path("login/",views.LoginView.as_view()), # 登录
path("index/images/",views.IndexImageView.as_view()), # 图片
path("info/",views.UserInfoView.as_view()), # 获取用户信息
path("addr/",views.AddrView.as_view()), # 用户收货地址信息
path("pwd/change/",views.ChangePwdView.as_view()), # 修改密码
]
4.创建模型类
根据要求创建模型类
# 用户模型
class User(models.Model):
username = models.CharField("用户名",max_length=32,unique=True)
password = models.CharField("密码",max_length=32)
mobile = models.CharField("手机号",max_length=16)
class Meta:
verbose_name = '用户表'
verbose_name_plural = verbose_name
def __str__(self):
return "%s (%s)" % (self.username,self.mobile)
5.判断用户名
后端
from rest_framework.response import Response
from rest_framework.views import APIView
from users.models import User,IndexImage,Addr
from django.http import HttpResponse
# 定义检查用户名的类试图
class CheckUserNameView(APIView):
def get(self,request,username):
# 判断用户名是否输入,没有输入 username = NULL
if not username:
return Response({
"code":400,
"msg":'用户没输入'
})
# 检测用户名长度
if not (6<= len(username) <= 32):
return Response({
"code":400,
"msg":'用户长度不符'
})
# 检测用户名是否存在
# 查询数据库有没有当前用户名
user_count = User.objects.filter(username=username).count()
if user_count:
# 根据用户名查询出的用户条数不为0
return Response({
"code":400,
"msg":'用户已存在'
})
return Response({
"code":200,
"msg":'用户输入成功'
})
前端
// 用户名的校验方法
let validateName = (rule, value, callback) => {
console.log("校验用户名,规则", rule, "用户名", value, "回调函数", callback)
// TODO 校验用户名
// 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
// 成功 return callback();
if (!value){
return
}
let url = "/user/check/username/" + value + "/";
this.$axios.get(url).then((result) => {
if (result.data.code == 200){
return callback();
}else{
return callback(new Error(result.data.msg));
}
}).catch((err) => {
console.log(err)
alert('判错')
});
};
6.判断手机号
后端
import re
# 手机号校验
class CheckMobileView(APIView):
def get(self,request,mobile):
rule = r'^1[3-9][0-9]{9}$' # 定义手机号正则
rs = re.findall(rule,mobile) # 返回结果是一个列表
if not rs:
return Response({
"code":400,
"msg":'手机格式不对'
})
# 手机号格式无误,就要进行唯一性校验
mobile_count = User.objects.filter(mobile=mobile).count()
if mobile_count:
return Response({
"code":400,
"msg":"手机号已存在"
})
return Response({
"code":200,
"msg":"手机号输入正确"
})
前端
// 手机号的校验方法
let validateMobile = (rule, value, callback) => {
console.log("校验手机号,规则", rule, "手机号", value, "回调函数", callback)
// TODO 校验手机号
// 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
// 成功 return callback();
if (!value){
return
}
let url = "/user/check/mobile/" + value + "/";
this.$axios.get(url).then((resp)=>{
if (resp.data.code == 200){
return callback();
}else{
return callback(new Error(resp.data.msg))
}
}).catch((err)=>{
console.log(err)
alert("报错")
})
};
7.检验密码
后端
# 密码校验
class CheckPasswordView(APIView):
def post(self,request):
pwd = request.data.get("pwd")
# 校验
if not (6<= len(pwd) <= 32):
return Response({
"code":400,
"msg":'密码长度不符'
})
return Response({
"code":200,
"msg":'密码输入成功'
})
前端
// 密码的校验方法
let validatePass = (rule, value, callback) => {
console.log("校验密码,规则", rule, "密码", value, "回调函数", callback)
// TODO 校验密码
// 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
// 成功 return callback();
if (!value){
return
}
let url = "/user/check/password/"
this.$axios.post(url,{"pwd":value}).then((resp)=>{
if (resp.data.code == 200){
return callback();
}else{
return callback(new Error(resp.data.msg))
}
}).catch((err)=>{
console.log(err)
alert("报错")
})
};
8.确认密码
后端
# 验证两次输入密码是否一致
class CheckPasswordView2(APIView):
def post(self,request):
pwd = request.data.get('pwd') # 密码
pwd1 = request.data.get("pwd1") # 再次输入密码
if pwd != pwd1:
return Response({
"code":400,
"msg":"密码不一致"
})
return Response({
"code":200,
"msg":"密码一致"
})
前端
// 确认密码的校验方法
let validateConfirmPass = (rule, value, callback) => {
console.log("校验确认密码,规则", rule, "二次输入的密码", value, "回调函数", callback)
// TODO 校验确认密码
// 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
// 成功 return callback();
let url = '/user/check/password2/';
this.$axios.post(url,{"pwd":this.RegisterUser.pass,"pwd1":value})
.then((resp)=>{
if(resp.data.code==200){
return callback();
}else{
return callback(new Error(resp.data.msg))
}
}).catch((err)=>{
console.log(err)
alert('报错')
})
};
9.生成验证码/检验验证码
后端
# 生成验证码
import random
class VerImageView(APIView):
def get(self,request,uuid):
# 1.生成创建验证码所需要的字符串 random
code = str(random.randint(1000,9999))
# 2.根据字符串变成图片
from captcha.image import ImageCaptcha
img = ImageCaptcha() # 实例化验证码的类
img_pic = img.generate(code) # 生成器生成验证码图片
print('生成的图片是', img_pic) # 返回值是夜歌IO字节流
# return HttpResponse(img_pic,content_type="image/png")
# 把验证码存到redis
import redis
r = redis.Redis(host="127.0.0.1",port=6379,password='123123')
r.set(uuid,code,ex=60 * 5) # 失效时间5分钟
print(uuid)
print(code)
return HttpResponse(img_pic, content_type="image/png")
class CheckCodeView(APIView):
def post(self,request):
code = request.data.get("code") # 用户输入的验证码
uuid = request.data.get("uuid") # 用户的唯一标志
# 1.连接数据库,取出uuid,对应的验证码
import redis
r = redis.Redis(host='127.0.0.1',password="123123")
sys_code = r.get(uuid)
# 如果uuid对应的数据为空,说明验证码已过期
if not sys_code:
return Response({
"code":400,
"msg":"验证码已过期"
})
# 将code转化为字符串
sys_code_str = sys_code.decode()
# 2.用户输入的验证码和数据库的验证码做比对
if sys_code_str != code:
# 如果不一致,验证码错误
return Response({
"code":400,
"msg":"验证码错误",
})
# 如果一致,索命验证码通过
return Response({
"code":200,
"msg":"校验通过"
})
前端
// 生成图片验证码地址
genImageCode() {
// 生成一个uuid
this.imageCodeID = uuid4()
// 生成一个图片验证码地址
this.iamgeCodeUrl = "user/check/image/" + this.imageCodeID + "/"
},
// 校验图片验证码
let validateImageCode = (rule, value, callback) => {
console.log("校验验证码,规则", rule, "二验证码", value, "回调函数", callback)
// TODO 校验验证码
// 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
// 成功 return callback();
this.$axios.post('/user/check/img/code/',{"uuid":this.imageCodeID,"code":value}).then((resp)=>{
if(resp.data.code==200){
return callback();
}else{
return callback(new Error(resp.data.msg))
}
}).catch((err)=>{
console.log(err)
alert("页面报错")
})
};
10.注册
后端
class RegView(APIView):
def post(self,request):
username = request.data.get('username')
password = request.data.get('password')
mobile = request.data.get('mobile')
agree = request.data.get('agree')
# 判断一下用户是否勾选协议
if not int(agree):
print(agree)
return Response({
"code":400,
"msg":"请勾选协议"
})
# 判断用户输入信息是否正确
if not username or not password or not mobile:
return Response({
"code":400,
"msg":"参数输入有误"
})
# TODO 检验用户名、密码、手机号
# 校验完毕,写入数据库
try:
User.objects.create(
username=username,
password=password,
mobile=mobile
)
return Response({
"code" :200,
"msg":"注册成功"
})
except Exception as e:
return Response({
"code":400,
"msg":"注册失败"
})
前端
// 用户注册
Register() {
// 是否同意用户协议
if (!this.aggree) {
this.flag = true
return
}
// 已勾选,则不显示提示信息
this.flag = false
// 通过element自定义表单校验规则,校验用户输入的用户信息
this.$refs["ruleForm"].validate((valid) => {
if (valid) {
// TODO 注册用户
this.$axios.post('/user/reg/',{
'username':this.RegisterUser.name,
'password':this.RegisterUser.pass,
'mobile':this.RegisterUser.mobile,
'agree':this.aggree,
}).then((resp)=>{
if(resp.data.code == 200){
// alert('注册成功')
// 清空数据
this.RegisterUser.name = ""
this.RegisterUser.pass = ""
this.RegisterUser.mobile = ""
this.RegisterUser.confirmPass = "",
this.RegisterUser.imageCode = "",
this.aggree = false
// 关闭注册弹窗
this.isRegister = false
this.notifySucceed(resp.data.msg)
}else{
// alert('注册失败')
this.notifyError(resp.data.msg)
}
}).catch((err)=>{
console.log(err)
alert('页面报错')
})
} else {
return false;
}
});
},