栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

用户注册练习

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用户注册练习

根据用户注册效果图,提取出用户模型类字段,进一步分析出 注册逻辑,并完成主要功能。

用户注册页面效果图

注册逻辑

  1. 生成页面的图片验证码,需要两种触发方式: 默认执行,点击执行

  2. 获取输入的用户名

    1. 利用正则校验用户名的合法性

    2. 当用户名正则校验通过,向 后端 发送请求,校验 用户名是否重复

  3. 获取密码

    1. 利用正则校验密码的合法性

  4. 获取确认密码

    1. 校验 确认密码和密码 是否一致

  5. 获取手机号

    1. 利用正则校验手机号的合法性

    2. 当手机号正则校验通过,向 后端 发送请求,校验手机号是否重复

  6. 获取用户输入的验证码

    1. 校验验证码是否存在

  7. 校验是否选择复选框,必须勾选

  8. 点击注册按钮,将信息提交到后端

 

用户表设计

用户表: 用户名、密码、手机号

可以自定义模型类,包含这些字段,在真正的项目开发中,不会自己重写一遍,而是继承 django内置的用户模型类: AbstractUser, 重写自己的字段, 但是需要在 settings.py 中 指明当前的用户模型类

在python项目,子应用的model文件里创建模型类

from django.db import models
# python会给我们自动创建一个用户表,我们只需要导入,应用一下就行了,也可以自己创建模型类
from django.contrib.auth.models import AbstractUser
# Create your models here.
# 定义类继承python创建的表
class User(AbstractUser):
    # 新增手机号字段
    mobile = models.CharField(max_length=11,verbose_name='手机号')
    class Meta:
        verbose_name='用户表'
        verbose_name_plural=verbose_name
        db_table = 'tb_user'
    def __str__(self):
        return self.username

创建好后,我们需要在根项目里的settings中配置一下

AUTH_USER_MODEL = 'user.User'  # 使用自定义用户模型类  子应用名.模型类

然后我们就可以执行迁移操作了:

# 生成迁移文件
python manage.py makemigrations users
# 执行迁移操作
python manage.py migrate users

获取输入的用户名利用正则校验用户名的合法性,当用户名正则校验通过,向 后端发送请求,校验用户名是否重复 :

前端:

if(!value){
        return callback(new Error('用户名不能为空'))
      }else{
        const username_rule=/^[a-zA-Z][a-zA-Z0-9]{2,16}$/
        if(username_rule.test(value)){
            this.$axios.get('/users/check/username/'+value+'/')
            .then(resp=>{
              console.log('请求判断用户名')
              if(resp.data.code == 200){
                this.$refs.ruleForm.validateField('cheskPass')
                return callback()
              }else{
                return callback(new Error(resp.data.msg))
              }
            })
            .catch(err=>{
              console.log(err)
              return Promise.reject()
            })
        }else{
          return callback(new Error('用户名格式错误'))
        }
      }

我们需要根据前端的接口,来编写后端的代码:

from rest_framework.views import APIView
from rest_framework.response import Response
from users.models import *

# Create your views here.
class CheckUsername(APIView):
    def get(self, request, username):
        """
        1. 用户名格式不正确,返回 404
        2. 用户名格式正确,用户名重复,返回 400
        3. 用户名格式正确,也不重复,返回 200
        """
        # 1. 判断用户名格式
        # 要求字母开头,中间为字母、数字、下划线,长度5-16
        if not re.find(r'^[a-zA-Z][a-zA-Z0-9_]{4,15}$', username):
        	return Response({"code":404, 'msg':"用户名格式不正确"})
        # 2. 根据用户名查询用户
        n = User.objects.filter(username=username).count()
        # 3. 判断
        if n == 0:
            return Response({"code": 200, 'msg': 'OK'})
        else:
            return Response({"code": 400, 'msg': '用户名重复'})

获取密码利用正则校验密码的合法性:

前端:

let validatePass = (rule, value, callback) => {
      if (value === "") {
        return callback(new Error("请输入密码"));
      }
      // 密码以字母开头,长度在6-18之间,允许字母数字和下划线
      const passwordRule = /^[a-zA-Z]w{5,17}$/;
      if (passwordRule.test(value)) {
        this.$refs.ruleForm.validateField("checkPass");
        return callback();
      } else {
        return callback(
          new Error("字母开头,长度6-18之间,允许字母数字和下划线")
        );
      }
    };
    // 确认密码的校验方法
    let validateConfirmPass = (rule, value, callback) => {
      if (value === "") {
        return callback(new Error("请输入确认密码"));
      }
      // 校验是否以密码一致
      if (this.RegisterUser.pass != "" && value === this.RegisterUser.pass) {
        this.$refs.ruleForm.validateField("checkPass");
        return callback();
      } else {
        return callback(new Error("两次输入的密码不一致"));
      }
    };

获取手机号,利用正则校验手机号的合法性,当手机号正则校验通过,向后端发送请求,校验手机号是否重复:

 前端:

if (!value){
        return callback(new Error('手机号码不能为空'))
      }else{
        const username_rule = /^1[3-9]d{9}$/
        if (username_rule.test(value)){
          this.$axios.get('/users/check/mobile/'+value+'/')
          .then(resp=>{
            console.log('请求判断手机号')
            if (resp.data.code == 200){
              this.$refs.ruleForm.validateField('checkPass')
              return callback()
            }else{
              return callback(new Error(resp.data.msg))
            }
          })
          .catch(err=>{
            console.log(err)
            this.Promise.reject()
          })
        }else{
          return callback(new Error('手机号码错误'))
        }
      }

 后端:

class CheckMobile(APIView):
    def get(self, request, mobile):
        """
        1. 手机号格式不正确,返回 404
        2. 手机号重复,返回 400
        3. 手机号格式正确,也不重复,返回 200
        """
        # 1. 校验手机号格式,前后端都需校验
        #手机号以1开头,第二位3-9之间的数字,长度为11,只允许数字
        if not re.findall(r"^1[3-9]d{9}$", mobile):
        	return Response({"code":404, 'msg':"手机号格式不正确"})
        # 2. 根据手机号查询用户数量
        n = User.objects.filter(mobile=mobile).count()
        # 3. 判断并返回结果
        if n == 0:
            return Response({"code":200, 'msg': 'OK'})
        else:
            return Response({"code":400, 'msg': '手机号重复'})
图片验证码

uuid, 唯一身份标识码, 在用户注册之前,网站没有任何东西来区分不同的客户端, 因此在客户端生成一个 uuid, django中通过不同的uuid来区分不同的客户端。

图片验证码生成与展示
  1. django后端

==路由匹配==

from django.urls import path
from user.views import *
urlpatterns = [
	#/users/image_code/xxx/ 生成图片验证码
    path('image_code//', ImageCode.as_view()), #也可以
]

     ==视图接口==

import random
import string
import redis
from django.http.response import HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *
from captcha.image import ImageCaptcha

class ImageCode(APIView):
    def get(self, request, uuid):
		# 1.接收参数uuid
		
		# 2. 生成随机字符串
        # string.ascii_letters: 所有字母的字符串(大小写)
        # string.digits: 所有的数字字符串(0-9)
        # random.sample: 随机采集指定位数的字符
        salt = ''.join(random.sample(string.ascii_letters + string.digits, 4))
        # 2. 生成 图片验证码 流
        img = ImageCaptcha()
        image = img.generate(salt) #io.BytesIO对象
        #from PIL import Image
        #im = Image.open(image)
        #im.show() #查看生成的图片验证码
        
        # 3. 连接redis
        redis_conn = redis.Redis(host='localhost', port=6379, db=0)

        # 4. 存储图片验证码,设置过期时间10分钟
        redis_conn.setex(str(uuid), 60 * 10, salt)

        # 5. 返回图片流
        return HttpResponse(image, content_type='image/png')

前端加载图片验证码 :





         
图片验证码认证

  1. django后端 

        ==路由配置== 

#校验图片验证码
#/users/check_image_code/?imageCodeID=xxx&imageCode=xxxx
path('check_image_code/', CheckImageCode.as_view()),

==视图接口==

class CheckImageCode(APIView):
    def get(self, request):
        """
        1. 接收前端发送的参数,imageCodeID & imageCode
        2. 取出redis中的 图片验证码
            如果取不到,说明过期,响应204
            如果取到验证码,进行对比,注意: 统一大小写
        3. 根据对比结果,返回响应
            对比成功,响应200
            对比失败,响应204
        """
        #1. 接收前端发送的参数,imageCodeID & imageCode
        uuid_ = request.query_params.get("imageCodeID")
        image_code_ = request.query_params.get("imageCode")

        # 2. 取出redis中的 图片验证码
        #     如果取不到,说明过期,响应204
        #     如果取到验证码,进行对比,注意: 统一大小写
        redis_conn = redis.Redis(host='localhost', port=6379, db=0)
        image_code = redis_conn.get(uuid_)

        if not image_code:
            return Response({"code":204, 'msg': '验证码过期'})

        # 3.
        # 根据对比结果,返回响应
        # 对比成功,响应200
        # 对比失败,响应204
        if image_code.decode().lower() == image_code_.lower():
            return Response({"code":200, 'msg': 'ok'})
        else:
            return Response({"code":204, 'msg': '验证码错误'})

Vue前端校验输入的图片验证码

// 校验图片验证码
let validateImageCode = (rule, value, callback) => {
  if (value === "") {
    return callback(new Error("请输入图片验证码"));
  }
  // 图片验证码是由字母、数字组成,长度为4
  const iamgeCodeRule = /^[a-zA-Z0-9]{4}$/;
  if (iamgeCodeRule.test(value)) {
    this.$axios.get("/users/check_image_code/", {
      params:{
        imageCodeID: this.imageCodeID,
        imageCode: this.RegisterUser.imageCode,
      }
    })
    .then(res => {
      if(res.data.code == 200){
        this.$refs.ruleForm.validateField("checkPass");
        return callback();
      }else{
        return callback(new Error(res.data.msg))
      }
    }).catch(err => {
      return Promise.reject(err)
    })
  } else {
    return callback(new Error("图片验证码不正确!"));
  }
};
用户注册

Vue前端接口 点击注册,触发函数如下:

// 用户注册
Register() {
  // 是否同意用户协议
  if(!this.aggree){
    this.flag = true
    return
  }
  // 已勾选,则不显示提示信息
  this.flag = false
  // 通过element自定义表单校验规则,校验用户输入的用户信息
  this.$refs["ruleForm"].validate((valid) => {
    //如果通过校验开始注册
    if (valid) {
      this.$axios
        .post("/users/register/", {
          userName: this.RegisterUser.name,
          pwd: this.RegisterUser.pass,
          mobile: this.RegisterUser.mobile,
          agree: this.aggree,
        })
        .then((res) => {
          // 200代表注册成功,其他的均为失败
          if (res.data.code == 200) {
            // 隐藏注册组件
            this.isRegister = false;
            // 弹出通知框提示注册成功信息
            this.notifySucceed(res.data.msg);
          } else {
            // 弹出通知框提示注册失败信息
            this.notifyError(res.data.msg);
          }
        })
        .catch((err) => {
          return Promise.reject(err);
        });
    } else {
      return false;
    }
  });
},

django后端

from rest_framework.views import APIView
from rest_framework.response import Response
from user.models import *

#注册
class Register(APIView):
    def post(self, request):
        # 前端传入 userName, pwd, mobile, agree
        username = request.data.get("userName")
        password = request.data.get("pwd")
        mobile = request.data.get("mobile")
        agree = request.data.get("agree")
        #验证参数
        if not all([username, password, mobile]):
            return Response({"code":204, "msg":"注册信息不完整!"})
        if not agree:
            return Response({"code":204, 'msg':"未同意用户使用协议"})

        # 存入数据库
        User.objects.create_user(username=username, password=password, mobile=mobile)

        # 返回响应
        return Response({"code":200, "msg":"注册成功!"})

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1002485.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号