大米商城注册

该博客介绍了使用Django REST框架搭建后端,包括配置settings,数据库设置,跨域处理,路由分发以及模型类创建。同时详细阐述了后端如何验证用户名、手机号、密码,并提供了前端校验方法。最后实现了注册功能,包括前端表单验证和后端数据写入。整个流程展示了前后端交互的完整过程。
摘要由CSDN通过智能技术生成

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;
        }
      });
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值