美文网首页
注册功能实现 -- 7.用户注册功能实现

注册功能实现 -- 7.用户注册功能实现

作者: 爱修仙的道友 | 来源:发表于2019-03-01 15:11 被阅读0次

    七、用户注册功能实现

    1.分析

    业务处理流程:

    • 判断用户名是否为空,是否已注册
    • 判断手机号是否为空,是否已注册
    • 判断密码是否为空,格式是否正确
    • 判断确认密码与密码是否相同
    • 判断短信验证码是否为空,是否格式正确,是否与真实的短信验证码相同

    请求方法POST

    url定义/users/register/

    请求参数:请求体传参

    参数 类型 前端是否必须传 描述
    username 字符串 用户输入的用户名
    password 字符串 用户输入的密码
    password_repeat 字符串 用户输入的重复密码
    mobile 字符串 用户输入的手机号
    user_sms_text 字符串 用户输入的短信验证码

    注:由于是post请求,在向后端发起请求时,需要附带csrf token

    2.后端代码实现

    # views.py
    from django.views import View
    from django.shortcuts import render
    from django.contrib.auth import login
    
    from .models import Users
    from .forms import RegisterForms
    from utils.res_code.rescode import Code, error_map
    from utils.json_translate.json_fun import to_json_data
    
    
    logger = logging.getLogger('django')
    
    # 用户注册逻辑实现
    class RegisterView(View):
        """
        用户注册逻辑视图
        -- get  
        -- post
        """
        def get(self, request):
            """
            渲染登陆页面
            :param request:
            :return:
            """
            return render(request, 'users/register.html')
    
        def post(self, request):
            """
            1.创建一个类视图 RegisterView
            2.明确请求方式:
                -- 请求类型 Ajax post
                -- 传参方式及参数 请求体  username  password  password_repeat mobile user_sms_text
                -- url路径 '/users/register/'
            3.获取前端数据
                -- json_data = request.body
            4.业务处理
                -- 是否需要校验            需要,form表单校验
                -- 是否需要储存            需要,mysql数据库存储用户信息
                -- 其他:
                    -- 日志器展示用户信息
                    -- 返回用户登陆界面
            5.返回前端数据:
                -- to_json_data(errno= ,errmsg=, data=)
            :param request:
            :return:
            """
            # 获取前端参数
            json_data = request.body
    
            # 若无参数
            if not json_data:
                return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
    
            # 将字节类型的json参数转化为dict
            dict_data = json.loads(json_data.decode('utf-8'))
    
            # form表单校验
            form = RegisterForms(dict_data)
            if form.is_valid():
                # 获取参数
                cleaned_mobile = form.cleaned_data.get('mobile')
                cleaned_password = form.cleaned_data.get('password')
                cleaned_username = form.cleaned_data.get('username')
    
                # 保存数据 mysql
                try:
                    user = Users.objects.create_user(username=cleaned_username, password=cleaned_password, mobile=cleaned_mobile)
                except Exception as e:
                    return to_json_data(errno=Code.SERVERERR, errmsg=error_map[Code.SERVERERR])
    
                # 自动处理session信息,保持登陆
                login(request, user)
                logger.info('恭喜{}用户注册成功'.format(user))
    
    
                return to_json_data(errno=Code.OK, errmsg='恭喜你注册成功')
            else:
                # 定义一个接收错误信息的列表
                form_errormsg_list = []
    
                for msg in form.errors.get_json_data().values():
                    form_errormsg_list.append(msg[0].get('message'))
                form_errormsg = '/'.join(form_errormsg_list)
    
                return to_json_data(errno=Code.PARAMERR, errmsg=form_errormsg)
    
    
    # forms.py
    import re
    
    from django import forms
    from django_redis import get_redis_connection
    from django.core.validators import RegexValidator
    
    from .models import Users
    from verifications.constants import SMS_CODE_NUMS
    
    
    password_Validator = RegexValidator(r'^\w{6,20}$', '密码格式不正确,请重新输入')
    # 注册表单校验
    class RegisterForms(forms.Form):
        """
           获取参数 --
               username password password_repeat mobile user_sms_text
           业务逻辑 --
               判断用户名是否符合标准(是否注册,是否为空,是否合法)
               判断手机号是否符合标准(是否注册,是否为空,是否合法)
               判断密码是否符合标准(是否为空,格式是否正确)
               判断确认密码是否符合标准(是否为空,格式是否正确,是否与密码相同)
               判断短信密码是否符合标准(是否为空,格式是否正确,是否与redis保存的相同)
        """
        username = forms.CharField(max_length=20, min_length=5, label='用户名',
                                   error_messages={
                                       'max_length':'用户名长度要小于20字符',
                                       'min_length':'用户名长度要大于5字符',
                                       'required':'用户名不能为空'
                                   })
    
        password = forms.CharField(max_length=20, min_length=6, label='密码',  validators=[password_Validator,],
                                   error_messages={
                                       'max_length':'密码长度要小于20位',
                                       'min_length':'密码长度要大于6位',
                                       'required':'密码不能为空',
                                   })
    
        password_repeat = forms.CharField(max_length=20, min_length=6, label='密码',  validators=[password_Validator,],
                                   error_messages={
                                       'max_length':'密码长度要小于20位',
                                       'min_length':'密码长度要大于6位',
                                       'required':'密码不能为空',
                                   })
    
        mobile = forms.CharField(max_length=11, min_length=11, label='手机号',
                                 error_messages={
                                     'max_length':'手机号长度要为11位',
                                     'min_length':'手机号长度要为11位',
                                     'required':'手机号不能为空',
                                 })
    
        user_sms_text = forms.CharField(max_length=SMS_CODE_NUMS, min_length=SMS_CODE_NUMS, label='短信验证码',
                                        error_messages={
                                            'max_length':'短信验证码输入有误',
                                            'min_length':'短信验证码输入有误',
                                            'required':'短信验证码不能为空'
                                        })
    
        def clean_username(self):
            cleaned_username = self.cleaned_data.get('username')
            if Users.objects.filter(username=cleaned_username).count():
                raise forms.ValidationError('该用户名已经注册')
            return cleaned_username
    
        def clean_mobile(self):
            cleaned_mobile = self.cleaned_data.get('mobile')
            if not re.match(r'^1[3-9]\d{9}$', cleaned_mobile):
                raise forms.ValidationError('输入手机号格式不正确')
            if Users.objects.filter(mobile=cleaned_mobile).count():
                raise forms.ValidationError('该手机号已经注册')
            return cleaned_mobile
    
        def clean(self):
            """
            password password_repeat
            user_sms_text redis_sms_text
            :return:
            """
            cleaned_data = super().clean()
            cleaned_password = cleaned_data.get('password')
            cleaned_password_repeat = cleaned_data.get('password_repeat')
    
            if cleaned_password != cleaned_password_repeat:
                raise forms.ValidationError('两次密码输入不一致')
    
            cleaned_mobile = cleaned_data.get('mobile')
            cleaned_user_sms_text = cleaned_data.get('user_sms_text')
    
            # 读取短信验证码(redis)
            try:
                # redis 读取数据操作三部曲
                # 1.连接redis
                conn_redis = get_redis_connection(alias='verify_codes')
                # 2.建立key值    -- 二进制形式
                sms_text_key = 'sms_text_{}'.format(cleaned_mobile).encode('utf-8')
                # 3.读取数据
                redis_sms_content = conn_redis.get(sms_text_key)
            except Exception as e:
                raise forms.ValidationError('数据库连接错误')
    
            if not redis_sms_content or (redis_sms_content.decode('utf-8') != cleaned_user_sms_text):
                raise forms.ValidationError('验证码输入错误')
    
    
    
    # urls.py
    from django.urls import path
    from . import views
    
    app_name = 'users'
    
    urlpatterns = [
        path('login/', views.LoginView.as_view(), name='user_login'),
        path('register/', views.RegisterView.as_view(), name='user_register'),
    ]
    
    

    3.前端代码实现

    # register.py
     //---------------------注册逻辑-------------------------//
    
         let $register = $('.form-contain');  // 获取注册表单元素
        $register.submit(function (e) {
            // 阻止默认提交
            e.preventDefault();
    
            // 获取用户输入内容:
    
            let sUsername = $username.val();
            let sPassword = $('input[name=password]').val();
            let sPassword_Repeat = $('input[name=password_repeat]').val();
            let sMobile = $mobile.val();
            let sSmsCode = $('input[name=sms_captcha]').val();
    
            //判断用户名是否已注册
            let susername = fn_check_username();  //不加async: false,永远返回define/""
            if (susername===''){
                return
            }
    
            // 判断手机号是否为空,是否已注册
            let smobile = fn_check_mobile();
            if (smobile===''){
                return
            }
    
            // 判断用户输入的密码是否为空
            if ((!sPassword) || (!sPassword_Repeat)) {
                message.showError('密码或确认密码不能为空');
                return
            }
    
            // 判断用户输入的密码和确认密码长度是否符合标准
            if (!(/^\w{6,20}$/).test(sPassword)) {
                message.showError('密码格式:匹配包括下划线的任何英文单词字符');
                return
            }
            if (!(/^\w{6,20}$/).test(sPassword_Repeat)) {
                message.showError('密码格式:匹配包括下划线的任何英文单词字符');
                return
            }
    
            // 判断用户输入的密码和确认密码是否一致
            if (sPassword !== sPassword_Repeat) {
                message.showError('密码和确认密码不一致');
                return
            }
    
            // 判断用户输入的短信验证码是否为6位数字
            if (!(/^\d{6}$/).test(sSmsCode)) {
                message.showError('短信验证码格式不正确,必须为6位数字!');
                return
            }
    
            // 发起注册请求
            // 1、创建请求参数
            let SdataParams = {
                "username": sUsername,
                "password": sPassword,
                "password_repeat": sPassword_Repeat,
                "mobile": sMobile,
                "user_sms_text": sSmsCode
            };
    
            // 2、创建ajax请求
            $.ajax({
                // 请求地址
                url: "/users/register/",  // url尾部需要添加/
                // 请求方式
                type: "POST",
                data: JSON.stringify(SdataParams),
                // 请求内容的数据类型(前端发给后端的格式)
                contentType: "application/json; charset=utf-8",
                // 响应数据的格式(后端返回给前端的格式)
                dataType: "json"
            })
                .done(function (res) {
                    if (res.errno === "200") {
                        // 注册成功
                        message.showSuccess('恭喜你,注册成功!');
                        setTimeout(function () {
                            // 注册成功之后重定向到主页
                            window.location.href = '/users/login/';
                        }, 1000)
                    } else {
                        // 注册失败,打印错误信息
                        message.showError(res.errmsg);
                    }
                })
                .fail(function () {
                    message.showError('服务器超时,请重试!');
                });
            });
    
    
    
    
    
        //----------------------------------------------//
        // 这三步 可以将ajax的post请求添加 csrf
        // get cookie using jQuery
        function getCookie(name) {
            let cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                let cookies = document.cookie.split(';');
                for (let i = 0; i < cookies.length; i++) {
                    let cookie = jQuery.trim(cookies[i]);
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
    
        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
    
        // Setting the token on the AJAX request
        $.ajaxSetup({
            beforeSend: function (xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
                }
            }
        });
    
        //----------------------------------------------//
    

    相关文章

      网友评论

          本文标题:注册功能实现 -- 7.用户注册功能实现

          本文链接:https://www.haomeiwen.com/subject/gexcuqtx.html