[django项目] 用户注册功能 之 用户名与手机号校验

前言

书接上文, 完成了图片验证码之后, 接下来就是对用户名密码和手机号的校验
相比较而言密码的校验围绕前端代码, 不涉及后台校验, 因此本文密码校验篇幅较少,为的是着重讲解的是用户名和手机号的校验.

V. 用户名校验

判断用户名是否被注册, 提示验证信息到页面

1>接口设计

1.1>接口说明
类目说明
请求方法GET
url定义/username/(?P<username>\w{5,20})/
参数格式url路径参数
1.2>参数说明
参数名类型是否必须描述
username字符串输入的用户名
1.3>返回结果
{
    "errno": "0", 
 	"errmsg": "OK", 
 	"data": {
        "username": "username",			# 查询的用户名
        "count": 1						# 用户名查询的数量
    }
}

2>后端代码

编写用户验证使用已有的verification应用模块, 也就是之前做图片验证码时创建的

如果没有创建该模块,请创建新的app verification专门用来处理验证

cd ~/code/tztz/apps/
python ../manage.py startapp verification

别忘了在settings文件中注册app

2.1>verification/views.py代码
from user.models import User
from utils.json_res import json_response


def check_username_view(request, username):
    """
    检测用户名的有效性, 从前端
    GET username/(?P<username>\w{5,20})/
    """
    # 去数据库查询用户名,通过判断数量可以获知该用户是否存在
    data = {
        "errno": "0",
        "errmsg": "OK",
        "data": {
            "username": "username",  # 查询的用户名
            # 用户名查询的数量
            "count": User.objects.filter(username=username).count()  
        }
    }
    # 将数据传输到路由,使JS代码进行进一步的处理
    return JsonResponse(data)

这种写法使代码太过于冗余, 会影响到后续的维护, 为此下文会使用一个解决方法来代替这种写法

2.2>verification/urls.py代码
from django.urls import path, re_path
from . import views
# url的命名空间
app_name = 'verification'

urlpatterns = [
    path('image_code/', views.image_code_view, name='image_code'),
    # 带有正则表达式的URL路径, 需要使用re_path
    re_path('username/(?P<username>\w{5,20})/', views.check_username_view, name='check_username'),
]

配置好后可以尝试在浏览器中打开该url, 看一下是否会返回我们预期的响应

3>前端页面代码

user/register.html代码

{% extends 'base/base.html' %}
{% load static %}
{% block title %}注册{% endblock title %}

{% block link %}
<link rel="stylesheet" href="{% static 'css/user/auth.css' %}">
{% endblock link %}

{% block main_start %}
    <main id="container">
  <div class="register-contain">
    <div class="top-contain">
      <h4 class="please-register">请注册</h4>
      <a href="javascript:void(0);" class="login">立即登录 &gt;</a>
    </div>
    <form action="" method="post" class="form-contain">


      <div class="form-item">
        <input type="text" placeholder="请输入用户名" id="username" name="username" class="form-control" >
      </div>
      <div class="form-item">
        <input type="password" placeholder="请输入密码" name="password" class="form-control">
      </div>
      <div class="form-item">
        <input type="password" placeholder="请输入确认密码" name="password_repeat" class="form-control">
      </div>
      <div class="form-item">
        <input type="tel" placeholder="请输入手机号" name="telephone" class="form-control" autocomplete="off">
      </div>
      <div class="form-item">
        <input type="text" placeholder="请输入图形验证码" name="captcha_graph" class="form-captcha">
        <a href="javascript:void(0);" class="captcha-graph-img">
          <img src="{% url 'verification:image_code' %}" alt="验证码" title="点击刷新">
        </a>
      </div>
      <div class="form-item">
        <input type="text" placeholder="请输入短信验证码" name="sms_captcha" class="form-captcha" autocomplete="off">
        <a href="javascript:void(0);" class="sms-captcha" title="发送验证码">获取短信验证码</a>
      </div>
      <div class="form-item">
        <input type="submit" value="立即注册" class="register-btn">
      </div>
    </form>
  </div>
</main>
{% endblock main_start %}

{% block script %}
    <script src="{% static 'js/user/auth.js' %}"></script>
{% endblock script %}

4>前端js代码

要提前在base中引用message.js代码, 继续编写regiester.js代码

4.1>用户名校验
// 2. 用户名校验,光标离开,用户名输入框就校验用户名
let $username = $('#user_name');
$username.blur(fnCheckUsername);

function fnCheckUsername() {
    isUsernameReady = false;
    let sUsername = $username.val();     // 获取前端页面输入框中的值
    if (sUsername === ''){
        // message为外部引用js代码, 主要是显示提示信息的功能
        message.showError('用户名不能为空!');
        return  // 使用return的目的是为了当满足当前条件的时候就停止执行后续的判断
    }
    if (!(/^\w{5,20}$/).test(sUsername)){
        message.showError('用户名长度必须为5-20位!');
        return
    }
    $.ajax({
        // 发送ajax请求,从路由中获取信息,然后进行处理

        url:'/username/' + sUsername,
        type:'GET',
        dataType: 'json',
        // 路由中的信息是由后端的视图函数发送到前端的数据:count,username
        success: function (data) {
            if (data.data.count === 0){
                // 判断数量确认该用户是否存在
                message.showInfo(sUsername + '可以使用');
                isUsernameReady = true;
            }else{
                message.showError(sUsername + '已存在, 请重新输入!')
            }
        },
        error: function (xhr, msg) {
            message.showError('服务器错误请稍后重试!')
        }
    })
}

5>密码校验

密码校验不涉及后端代码, 主要是对前端的数据进行判断

// 3. 密码校验,判断两次密码是否一致
let $passwordRepeat = $('input[name="password_repeat"]');
$passwordRepeat.blur(fnCheckPassword);

 function fnCheckPassword () {
    isPasswordReady = false;
    let password = $('input[name="password"]').val();
    let passwordRepeat = $passwordRepeat.val();
    if (password === '' || passwordRepeat === ''){
        message.showError('密码不能为空');
        return
    }
    if (!(/^\w{6,18}$/).test(password)){
        message.showError('密码长度必须为6-18位!');
        return
    }
    if (password !== passwordRepeat){
        message.showError('两次密码输入不一致');
        return
    }
    if (password === passwordRepeat){
        isPasswordReady = true
    }
}

VI. json响应数据结构设计

用户名与手机号验证的方法非常相似, 这使得大量代码冗余, 可以对其进行优化

目的
  1. 减少代码冗余,提高复用性,解耦
  2. 分工协作
1.结构设计

实际项目是多人协同开发,特别是前后端交互,后端返回数据结构要一致。

{"errno": "0", "errmsg": "OK", "data": {...}}
字段类型说明
errno字符串错误编码
errmsg字符串错误信息
data返回数据

在项目根目录中utils文件夹下创建res_code.py文件,用于定义错误编码,代码如下:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
# author: hao 2019/8/10-20:09
class Code:
    """
    错误代码,在引发错误的时候作为错误的标志
    """
    OK = "0"
    DBERR = "4001"
    NODATA = "4002"
    DATAEXIST = "4003"
    DATAERR = "4004"
    METHERR = "4005"
    SMSERROR = "4006"
    SMSFAIL = "4007"

    SESSIONERR = "4101"
    LOGINERR = "4102"
    PARAMERR = "4103"
    USERERR = "4104"
    ROLEERR = "4105"
    PWDERR = "4106"

    SERVERERR = "4500"
    UNKOWNERR = "4501"


error_map = {
    # 错误信息,与错误代码对应
    Code.OK: "成功",
    Code.DBERR: "数据库查询错误",
    Code.NODATA: "无数据",
    Code.DATAEXIST: "数据已存在",
    Code.DATAERR: "数据错误",
    Code.METHERR: "方法错误",
    Code.SMSERROR: "发送短信验证码异常",
    Code.SMSFAIL: "发送短信验证码失败",

    Code.SESSIONERR: "用户未登录",
    Code.LOGINERR: "用户登录失败",
    Code.PARAMERR: "参数错误",
    Code.USERERR: "用户不存在或未激活",
    Code.ROLEERR: "用户身份错误",
    Code.PWDERR: "密码错误",

    Code.SERVERERR: "内部错误",
    Code.UNKOWNERR: "未知错误",
}
2.快捷方法

为了方便定义一个快捷方法,在utils目录下创建json_res.py文件代码如下:

from django.http import JsonResponse

from .res_code import Code


def json_response(erron=Code.OK, errmsg='', data=None, kwargs=None):
    """
    该方法实现的目的是为了使json数据在传输过程中,能够携带错误代码之类的信息
    :param erron: 错误代码
    :param errmsg: 错误信息
    :param data: 携带的用户信息数据,例如用户名,手机号等
    :return: 返回的相当于是我们处理好的json响应
    """
    json_dict = {
        'erron': erron,
        'errmsg': errmsg,
        'data': data,
    }
    if kwargs and isinstance(kwargs, dict):
        # 判断kwargs中是否有传输数据信息, 有则更新我们已有的信息
        json_dict.update(kwargs)
    return JsonResponse(json_dict)

VI. 判断手机号码是否注册功能

1>接口设计

1.1>接口说明:
类目说明
请求方法GET
url定义/mobile/(?P<mobile>1[3-9]\d{9})/
参数格式url路径参数
1.2>参数说明:
参数名类型是否必须描述
moblie字符串输入的手机号码
1.3>返回结果:
{
    "errno": "0", 
 	"errmsg": "OK", 
 	"data": {
        "mobile": "13xxxxxxxxx",			# 查询的手机号
        "count": 1						# 手机号查询的数量
    }
}

2>后端代码

2.1>verification/views.py代码

这里正好可以使用我们之前创建的json_response方法

# ····
def check_mobile_view(request, mobile):
    """
    校验手机号是否存在
    GET /moblie/(?P<moblie>1[3-9]\d{9})/
    """
    data = {
        'mobile': mobile,
        'count': User.objects.filter(mobile=mobile).count()
    }

    return json_response(data=data)
2.2>verification/urls.py
from django.urls import path, re_path
from . import views
# url的命名空间
app_name = 'verification'

urlpatterns = [
    path('image_code/', views.image_code_view, name='image_code'),
    re_path('username/(?P<username>\w{5,20})/', views.check_username_view, name='check_username'),
    re_path('mobile/(?P<mobile>1[3-9]\d{9})/', views.check_mobile_view, name='check_mobile'),
]
3. 前端js代码
$(function () {
    // 定义状态变量
    let isUsernameReady = false,
        isPasswordReady = false,
        isMobileReady = false,
        isSmsCodeReady = false;
    // 1.点击刷新图像验证码
    let $img = $('.form-contain .form-item .captcha-graph-img img');

    $img.click(function () {...});

    // 2.鼠标离开用户名输入框校验用户名
    let $username = $('#username');
    $username.blur(fnCheckUsername);

    function fnCheckUsername () {...}

    // 3.检测密码是否一致
    let $passwordRepeat = $('input[name="password_repeat"]');
    $passwordRepeat.blur(fnCheckPassword);

    function fnCheckPassword () {...}

    // 4.检查手机号码是否可用
    let $mobile = $('input[name="mobile"]');
    $mobile.blur(fnCheckMobile);

    function fnCheckMobile () {
        isMobileReady = true;
        let sMobile = $mobile.val();
        if(sMobile === ''){
            message.showError('手机号码不能为空');
            return
        }
        if(!(/^1[3-9]\d{9}$/).test(sMobile)){
            message.showError('手机号码格式不正确');
            return
        }

        $.ajax({
            url: '/mobile/' + sMobile + '/',
            type: 'GET',
            dataType: 'json',
            success: function (data) {
                if(data.data.count !== 0){
                    message.showError(data.data.mobile + '已经注册,请重新输入!')
                }else {
                    message.showInfo(data.data.mobile + '可以正常使用!');
                    isMobileReady = true
                }
            },
            error: function (xhr, msg) {
                message.showError('服务器超时,请重试!')
            }
        });

    }
});

使用Jquery的这种写法也可以实现同样的功能, 而且相比较而言更简便

$   //使用Jquery验证手机号的方式
    .ajax({
    // 发送ajax请求,从路由中获取信息,然后进行处理
    url: '/mobile/' + sMobile + '/',    // 末尾最好加上一个斜杠避免出错
    type: 'GET',    // 请求类型
    dataType: 'json',   // 返回的数据类型
	})
    .done((res)=>{
    if (res.data.count === 0) {
        message.showInfo(res.data.mobile + '可以使用');
        isMobileReady = true;
    } else {
        message.showError(res.data.mobile + '已注册, 请重新输入!')
    }
	})
    .fail(()=>{
    message.showError('服务器错误请稍后重试!')
	})

项目源码:https://gitee.com/hao4875/newssite

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值