我是靠谱客的博主 甜蜜云朵,最近开发中收集的这篇文章主要介绍Django项目实战——2—(用户注册前端接口设计、用户注册后端逻辑、验证码)1、用户注册前端接口设计2、用户注册后端逻辑3、验证码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、用户注册前端接口设计

请求方式

在这里插入图片描述

请求参数:表单参数

在这里插入图片描述

响应结果

在这里插入图片描述

用户注册接口定义

"""
视图文件

apps/users/views.py文件
"""
from django.shortcuts import render
from django.http import HttpResponse
from django.views import View


class RegisterView(View):
    """用户注册"""
    
    def get(self, request):
        """提供用户的注册界面"""
        return render(request, "register.html")
    
    def post(self, request):
        """提供用户的注册逻辑"""
        # 前端用户提交数据
        # 接收参数
        # 验证参数
        # 返回响应
        
        pass   

用户注册前端逻辑

使用Vue.js的双向绑定实现用户的交互和页面局部刷新效果。

用户注册页面绑定Vue数据

templates/register.html 用户注册界面

{#  templates/register.html  前端注册界面  #}
{% load static %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>LG商城-注册</title>
	<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
	<link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">
</head>
<body>
<!--绑定vue的app-->
<div id="app">
	<div class="register_con">
		<div class="l_con fl">
			<a href="index.html" class="reg_logo"><img src="{% static 'images/1.png' %}"></a>
			<div class="reg_slogan">商品美 · 种类多 · 欢迎光临</div>
			<div class="reg_banner"></div>
		</div>
		<div class="r_con fr">
			<div class="reg_title clearfix">
				<h1>用户注册</h1>
				<a href="login.html">登录</a>
			</div>
			<div class="reg_form clearfix">
<!--             v-cloak:解决Vue界面加载延迟的bug   @submit="on_submit"提交注册信息前的验证   -->
				<form method="post" class="register_form" v-cloak @submit="on_submit">
                    {% csrf_token %}
					<ul>
						<li>
							<label>用户名:</label>
<!--                        绑定Vue的名称v-model      @blur="check_username"是方法:当标签失去焦点,即鼠标光标消失 -->
							<input type="text" name="username" v-model="username" @blur="check_username" id="user_name">
<!--						当输入信息不合法,使用v-show标签是个bool类型的值,通过ajax传递信息到前端界面	 v-show为False时候,元素信息会被隐藏-->
                            <span class="error_tip" v-show="error_name">[[ error_name_message ]]</span>
						</li>					
						<li>
							<label>密码:</label>
<!--                              绑定Vue的名称v-model           -->
							<input type="password" name="password" v-model="password" @blur="check_password" id="pwd">
							<span class="error_tip" v-show="error_password">请输入8-20位的密码</span>
						</li>
						<li>
							<label>确认密码:</label>
<!--                          绑定Vue的名称v-model   -->
							<input type="password" name="password2" v-model="password2" @blur="check_password2" id="cpwd">
							<span class="error_tip" v-show="error_password2">两次输入的密码不一致</span>
						</li>
						<li>
							<label>手机号:</label>
                            <!--                          绑定Vue的名称v-model   -->
							<input type="text" name="mobile" v-model="mobile" @blur="check_mobile" id="phone">
<!--                        [[ error_mobile_message ]]是为了解决Vue识别不了{{ error_mobile_message }}语法的问题    -->
							<span class="error_tip" v-show="error_mobile">[[ error_mobile_message ]]</span>
						</li>
						<li>
							<label>图形验证码:</label>
							<input type="text" name="image_code" id="pic_code" class="msg_input">
							<img src="{% static 'images/pic_code.jpg'%}" alt="图形验证码" class="pic_code">
							<span class="error_tip">请填写图形验证码</span>
						</li>
						<li>
							<label>短信验证码:</label>
							<input type="text" name="sms_code" id="msg_code" class="msg_input">
							<a href="javascript:;" class="get_msg_code">获取短信验证码</a>
							<span class="error_tip">请填写短信验证码</span>
						</li>
						<li class="agreement">
<!--                        type="checkbox" 需要使用@change方法来判定焦点的信息      绑定Vue的名称v-model            -->
							<input type="checkbox" name="allow" v-model="allow" @change="check_allow"  id="allow">
							<label>同意”LG商城用户使用协议“</label>
						<!--	当输入信息不合法,使用v-show标签是个bool类型的值,通过ajax传递信息到前端界面	 v-show为False时候,元素信息会被隐藏-->
							<span class="error_tip" v-show="error_allow">请勾选用户协议</span>
						</li>
						<li class="reg_sub">
							<input type="submit" value="注 册">
						</li>
					</ul>				
				</form>
			</div>
		</div>
	</div>
	<div class="footer no-mp">
		<div class="foot_link">
			<a href="#">关于我们</a>
			<span>|</span>
			<a href="#">联系我们</a>
			<span>|</span>
			<a href="#">招聘人才</a>
			<span>|</span>
			<a href="#">友情链接</a>		
		</div>
		<p>CopyRight © 2016 北京LG商业股份有限公司 All Rights Reserved</p>
		<p>电话:010-****888    京ICP备*******8号</p>
	</div>
</div>
    <!--  引入Vue前端框架和ajax用于发送验证信息到前端界面  -->
    <script src="{% static 'js/vue-2.5.16.js' %}"></script>
    <script src="{% static 'js/axios-0.18.0.min.js' %}"></script>
    <!--  引入注册界面的js文件   -->
    <script src="{% static 'js/register.js' %}"></script>

</body>
</html>

static/js/register.js文件,验证注册界面的逻辑,绑定内容:变量、事件、错误提示等

// 实例化Vue的对象   static/js/register.js文件,验证注册界面的逻辑
let vm = new Vue({
    el:"#app",
    // 修改Vue读取变量的语法 {{}}  [[]],Vue中可能不识别Django的{{}}语法形式
    delimiters: ['[[', ']]'],

    data: {
        // v-model绑定名称
        username:"",    //绑定前端界面的username标签
        password:"",
        password2:"",
        mobile:"",
        allow:"",

        // v-show绑定的名称,默认false不显示
        error_name: false,
        error_password: false,
        error_password2: false,
        error_mobile: false,
        error_allow: false,

        // 绑定的错误信息
        error_name_message:"",
        error_mobile_message:"",
    },
    methods: {
        // 定义方法   定义标签失去焦点的方法
        // check_username:function () {
        // }

        // @blur="check_username"方法
        check_username(){
            // 正则表达式  5-20位字符数字组成
            let re = /^[a-zA-Z0-9_-]{5,20}$/;
            if(re.test(this.username)){
                // 匹配成功   错误信息不展示
                this.error_name = false
            }else{
                this.error_name = true  // v-show为true,显示信息
                this.error_name_message = "请输入5-20个字符的用户"
            }
        },

        // @blur="check_password"
        check_password(){
            let re = /^[a-zA-Z0-9]{8,20}$/;
            if(re.test(this.password)){
                this.error_password = false
            }else{
                this.error_password = true
            }
        },

        //  @blur="check_password2"
        check_password2(){
            // 保持一致就行
            if(this.password2 != this.password){
                this.error_password2 = true
            }else{
                this.error_password2 = false
            }
        },

        // @blur="check_mobile"
        check_mobile(){
            let re = /^1[3456789]d{9}$/;
            if(re.test(this.mobile)){
                this.error_mobile = false
            }else{
                this.error_mobile = true
                this.error_mobile_message = "请输入正确格式手机号!"
            }
        },

        // @change="check_allow"
        check_allow(){                        // checkbox的选中状态
            if(!this.allow){                  // allow是个空的bool类型值
                this.error_allow = true
            }else{
                this.error_allow = false
            }
        },

        // on_submit
        on_submit(){
            // 如果表单验证中有true就说明有错误信息,不能提交
            if(this.error_name == true || this.error_password == true || this.error_password2 ==true ||
            this.error_mobile == true || this.error_allow == true){
                // 禁止表单提交
                window.event.returnValue=false
            }
        },

    },
});

2、用户注册后端逻辑

校验参数

前端校验过的后端也要校验,后端的校验和前端的校验是一致的。

# 判断参数是否齐全
# 判断用户名是否是5-20个字符
# 判断密码是否是8-20个数字
# 判断两次密码是否一致
# 判断手机号是否合法
# 判断是否勾选用户协议

后端表单验证文件apps/users/forms.py

# -*- encoding: utf-8 -*-
"""
@File    : forms.py
@Time    : 2020/7/28 16:16
@Author  : chen

后端表单验证文件:apps/users/forms.py
"""
from django import forms
from .models import User


class RegisterForm(forms.Form):     # 继承自forms.Form是只需要验证个别字段的信息,而继承自model.Form是需要验证所有的字段
    username = forms.CharField(max_length=20, min_length=5, error_messages={"min_length": "用户名长度不对",
                                                                            "max_length": "用户名长度不对"})
    password = forms.CharField(max_length=20, min_length=8, error_messages={"min_length": "密码长度不对",
                                                                            "max_length": "密码长度不对",
                                                                            "required": "密码必须填写"})
    password2 = forms.CharField(max_length=20, min_length=8, error_messages={"min_length": "密码长度不对",
                                                                            "max_length": "密码长度不对",
                                                                            "required": "密码必须填写"})
    allow = forms.BooleanField()
    mobile = forms.CharField(max_length=11, min_length=11, required=True, error_messages={"min_length": "手机号长度不对",
                                                                            "max_length": "手机号长度不对",
                                                                            "required": "手机号必须填写"})
    
    # 检测用户名是否已经在数据库中
    def clean_username(self):
        username = self.cleaned_data.get('username')
        username_exists = User.objects.filter(username=username).exists()      # 检查数据库中username是否存在
        if username_exists:
            raise forms.ValidationError('用户名已经存在')
        return username

    # 检测手机号是否已经在数据库中
    def clean_mobile(self):
        mobile = self.cleaned_data.get('mobile')
        mobile_exists = User.objects.filter(mobile=mobile).exists()  # 检查数据库中手机号是否存在
        if mobile_exists:
            raise forms.ValidationError('手机号已经存在')
        return mobile
    
    # 验证两次密码是否一致
    def clean(self):
        cleaned_data = super().clean()                   # 调用父类的clean方法
        password = cleaned_data.get('password')
        password2 = cleaned_data.get('password2')
        
        if password != password2:
            raise forms.ValidationError("两次密码不一致")
        return cleaned_data                              # 可以不返回值,建议使用返回值

保存注册数据

• 这里使用Django认证系统用户模型类提供的 create_user()方法创建新的用户。
• 这里 create_user()方法中封装了 set_password() 方法加密密码。

状态保持

• 如果需求是注册成功后即表示用户登入成功,那么此时可以在注册成功后实现状态保持
• 如果需求是注册成功后不表示用户登入成功,那么此时不用在注册成功后实现状态保持

login()方法介绍

  1. 用户登入本质:
    • 状态保持
    • 将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前浏览器的 cookie 和服务端的 session 中。
  2. login()方法:
    • Django用户认证系统提供了login()方法。
    • 封装了写入session的操作,帮助我们快速登入一个用户,并实现状态保持。
  3. login()位置:
    • django.contrib.auth.init.py文件中。
    login(request, user, backend=None)

在这里插入图片描述
视图文件
apps/users/views.py文件

"""
视图文件

apps/users/views.py文件
"""
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse, JsonResponse
from django.views import View
from .forms import RegisterForm
from .models import User
from django.contrib.auth import login


class RegisterView(View):
    """用户注册"""
    def get(self, request):
        """提供用户的注册界面"""
        return render(request, "register.html")
    
    def post(self, request):
        """提供用户的注册逻辑"""
        # 前端用户提交数据
        form = RegisterForm(request.POST)
        if form.is_valid():
            # 接收参数
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            mobile = form.cleaned_data.get('mobile')
            try:
                # user = User(username=username, password=password, mobile=mobile)
                # 下面的添加数据的方法是封装了加密等功能的函数,更安全
                users = User.objects.create_user(username=username, password=password, mobile=mobile)
            except:    # 如果保存数据失败
                return render(request, 'register.html', {'register_error_message': '注册失败'})
            
            # 保持用户登录的状态
            login(request, users)
            
            # 返回响应
            # return HttpResponse('success')
            return redirect(reverse('contents:index'))           # 注册成功,跳转到首页
        else:
            print(form.errors.get_json_data())
            # return HttpResponse("fail")
            # 返回注册错误信息到前端界面
            context = {
                'form_error': form.errors,
            }
            return render(request, 'register.html', context=context)
    
    
class UsernameExists(View):
    """ 判断用户名是否已经存在"""
    def get(self, request, username):     # username用户名
        count = User.objects.filter(username=username).count()      # 查询数据库中信息
        return JsonResponse({"code": 0, "errmsg": "OK", "count": count})   # 返回给前端界面
    

templates/register.html 前端注册界面

{#  templates/register.html  前端注册界面  #}
{% load static %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>LG商城-注册</title>
	<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
	<link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">
</head>
<body>
<!--绑定vue的app-->
<div id="app">
	<div class="register_con">
		<div class="l_con fl">
			<a href="index.html" class="reg_logo"><img src="{% static 'images/1.png' %}"></a>
			<div class="reg_slogan">商品美 · 种类多 · 欢迎光临</div>
			<div class="reg_banner"></div>
		</div>
		<div class="r_con fr">
			<div class="reg_title clearfix">
				<h1>用户注册</h1>
				<a href="login.html">登录</a>
			</div>
			<div class="reg_form clearfix">
<!--             v-cloak:解决Vue界面加载延迟的bug   @submit="on_submit"提交注册信息前的验证   -->
				<form method="post" class="register_form" v-cloak @submit="on_submit">
                    {% csrf_token %}
					<ul>
						<li>
							<label>用户名:</label>
<!--                        绑定Vue的名称v-model      @blur="check_username"是方法:当标签失去焦点,即鼠标光标消失 -->
							<input type="text" name="username" v-model="username" @blur="check_username" id="user_name">
<!--						当输入信息不合法,使用v-show标签是个bool类型的值,通过ajax传递信息到前端界面	 v-show为False时候,元素信息会被隐藏-->
                            <span class="error_tip" v-show="error_name">[[ error_name_message ]]</span>
						</li>					
						<li>
							<label>密码:</label>
<!--                              绑定Vue的名称v-model           -->
							<input type="password" name="password" v-model="password" @blur="check_password" id="pwd">
							<span class="error_tip" v-show="error_password">请输入8-20位的密码</span>
						</li>
						<li>
							<label>确认密码:</label>
<!--                          绑定Vue的名称v-model   -->
							<input type="password" name="password2" v-model="password2" @blur="check_password2" id="cpwd">
							<span class="error_tip" v-show="error_password2">两次输入的密码不一致</span>
						</li>
						<li>
							<label>手机号:</label>
                            <!--                          绑定Vue的名称v-model   -->
							<input type="text" name="mobile" v-model="mobile" @blur="check_mobile" id="phone">
<!--                        [[ error_mobile_message ]]是为了解决Vue识别不了{{ error_mobile_message }}语法的问题    -->
							<span class="error_tip" v-show="error_mobile">[[ error_mobile_message ]]</span>
						</li>
						<li>
							<label>图形验证码:</label>
							<input type="text" name="image_code" id="pic_code" class="msg_input">
							<img src="{% static 'images/pic_code.jpg'%}" alt="图形验证码" class="pic_code">
							<span class="error_tip">请填写图形验证码</span>
						</li>
						<li>
							<label>短信验证码:</label>
							<input type="text" name="sms_code" id="msg_code" class="msg_input">
							<a href="javascript:;" class="get_msg_code">获取短信验证码</a>
							<span class="error_tip">请填写短信验证码</span>
						</li>
						<li class="agreement">
<!--                        type="checkbox" 需要使用@change方法来判定焦点的信息      绑定Vue的名称v-model            -->
							<input type="checkbox" name="allow" v-model="allow" @change="check_allow"  id="allow">
							<label>同意”LG商城用户使用协议“</label>
						<!--	当输入信息不合法,使用v-show标签是个bool类型的值,通过ajax传递信息到前端界面	 v-show为False时候,元素信息会被隐藏-->
							<span class="error_tip" v-show="error_allow">请勾选用户协议</span>

{# 这部分传注册错误信息到前端界面是用的Django自带的,前端验证form表单信息我们采用的是  @submit="on_submit" 中的ajax进行验证,这是两种方式,选择一种就可以 #}
                        {#  将apps/users/views.py文件中的注册错误信息context进行循环   #}
                            <span class="error_tip">
                                {% if form_errors %}
                                    {% for key,error in form_errors.items %}
                                            {{ error }}
                                    {% endfor %}
                                {% endif %}
                            {# 保存用户注册数据失败的信息apps/users/views.py中传递的register_error_message             #}
                                {% if register_error_message %}
                                    {{ register_error_message }}
                                {% endif %} 
                            </span>
                        
						</li>
						<li class="reg_sub">
							<input type="submit" value="注 册">
						</li>
					</ul>				
				</form>
			</div>
		</div>
	</div>
	<div class="footer no-mp">
		<div class="foot_link">
			<a href="#">关于我们</a>
			<span>|</span>
			<a href="#">联系我们</a>
			<span>|</span>
			<a href="#">招聘人才</a>
			<span>|</span>
			<a href="#">友情链接</a>		
		</div>
		<p>CopyRight © 2016 北京LG商业股份有限公司 All Rights Reserved</p>
		<p>电话:010-****888    京ICP备*******8号</p>
	</div>
</div>
    <!--  引入Vue前端框架和ajax用于发送验证信息到前端界面  -->
    <script src="{% static 'js/vue-2.5.16.js' %}"></script>
    <script src="{% static 'js/axios-0.18.0.min.js' %}"></script>
    <!--  引入注册界面的js文件   -->
    <script src="{% static 'js/register.js' %}"></script>

</body>
</html>

用户名重复注册

用户名重复注册逻辑分析
在这里插入图片描述

用户名重复注册接口设计和定义

在这里插入图片描述
请求参数:路径参数
在这里插入图片描述
响应结果:JSON
在这里插入图片描述
static/js/register.js文件,验证注册界面用户名重复等问题,如果需要验证登录手机号的问题,可以自己仿照用户名重复判定的ajax方法进行编写代码。

// 实例化Vue的对象   static/js/register.js文件,验证注册界面的逻辑
let vm = new Vue({
    el:"#app",
    // 修改Vue读取变量的语法 {{}}  [[]],Vue中可能不识别Django的{{}}语法形式
    delimiters: ['[[', ']]'],

    data: {
        // v-model绑定名称
        username:"",    //绑定前端界面的username标签
        password:"",
        password2:"",
        mobile:"",
        allow:"",

        // v-show绑定的名称,默认false不显示
        error_name: false,
        error_password: false,
        error_password2: false,
        error_mobile: false,
        error_allow: false,

        // 绑定的错误信息
        error_name_message:"",
        error_mobile_message:"",
    },
    methods: {
        // 定义方法   定义标签失去焦点的方法
        // check_username:function () {
        // }

        // @blur="check_username"方法
        check_username(){
            // 正则表达式  5-20位字符数字组成
            let re = /^[a-zA-Z0-9_-]{5,20}$/;
            if(re.test(this.username)){
                // 匹配成功   错误信息不展示
                this.error_name = false
            }else{
                this.error_name = true  // v-show为true,显示信息
                this.error_name_message = "请输入5-20个字符的用户"
            }

            // 使用Vue的ajax进行表单验证
            if(this.error_name == false){        // 用户名正确情况
                // http://127.0.0.1:8000/users/usernames/用户名/count      路由格式
                let url = '/users/usernames/'+ this.username + '/count'    // url拼接

                // Vue发送ajax请求
                axios.get(url, {
                    responseType:'json'
                })
                // 请求成功
                .then(response=> {                // .then(function(response))
                    // 从apps/users/views.py文件返回的JsonResponse({"code": 0, "errmsg": "OK", "count": count})
                    if(response.data.count == 1 ){  // 用户名已经存在   count数据就是在views.py文件中传出的
                        this.error_name_message = '用户名已经存在'
                        this.error_name = true
                    }else{
                        this.error_name = false      //可以继续注册其他的字段
                    }
                })
                // 请求失败
                .catch(error =>{
                    console.log(error.response)         // 前端界面打印error.response
                })
            }
        },

        // @blur="check_password"
        check_password(){
            let re = /^[a-zA-Z0-9]{8,20}$/;
            if(re.test(this.password)){
                this.error_password = false
            }else{
                this.error_password = true
            }
        },

        //  @blur="check_password2"
        check_password2(){
            // 保持一致就行
            if(this.password2 != this.password){
                this.error_password2 = true
            }else{
                this.error_password2 = false
            }
        },

        // @blur="check_mobile"
        check_mobile(){
            let re = /^1[3456789]d{9}$/;
            if(re.test(this.mobile)){
                this.error_mobile = false
            }else{
                this.error_mobile = true
                this.error_mobile_message = "请输入正确格式手机号!"
            }
        },

        // @change="check_allow"
        check_allow(){                        // checkbox的选中状态
            if(!this.allow){                  // allow是个空的bool类型值
                this.error_allow = true
            }else{
                this.error_allow = false
            }
        },

        // on_submit
        on_submit(){
            // 如果表单验证中有true就说明有错误信息,不能提交
            if(this.error_name == true || this.error_password == true || this.error_password2 ==true ||
            this.error_mobile == true || this.error_allow == true){
                // 禁止表单提交
                window.event.returnValue=false
            }
        },

    },
});

3、验证码

图形验证码逻辑分析

在这里插入图片描述
新建应用verifications

  • 将图形验证码的文字信息保存到Redis数据库,为短信验证码做准备。
  • UUID 用于唯一区分该图形验证码属于哪个用户,也可使用其他唯一标识信息来实现。
    在这里插入图片描述

图形验证码接口设计和定义

请求方式
在这里插入图片描述
请求参数:路径参数
在这里插入图片描述
验证码的视图文件apps/verifications/views.py

"""
apps/verifications/views.py   验证码视图文件
"""
from django.shortcuts import render
from django.views import View
from django.http import HttpResponse


class ImageCodeView(View):
    """图像验证码"""
    
    def get(self, request, uuid):
        """
        :param request: 请求对象
        :param uuid: 唯一标识图形验证码所属于的用户
        :return: image/jpg
        """
        return HttpResponse('image/jpg')
        

验证码路由文件:apps/verifications/urls.py

# -*- encoding: utf-8 -*-
"""
@File    : urls.py
@Time    : 2020/7/29 19:14
@Author  : chen


apps/verifications/urls.py   验证码路由文件
"""
from django.urls import path, include, re_path
from . import views

urlpatterns = [
    re_path('image_codes/(?P<uuid>[w-]+)/', views.ImageCodeView.as_view()),      # 图形验证码子路由
  
]

实现效果:
在这里插入图片描述

最后

以上就是甜蜜云朵为你收集整理的Django项目实战——2—(用户注册前端接口设计、用户注册后端逻辑、验证码)1、用户注册前端接口设计2、用户注册后端逻辑3、验证码的全部内容,希望文章能够帮你解决Django项目实战——2—(用户注册前端接口设计、用户注册后端逻辑、验证码)1、用户注册前端接口设计2、用户注册后端逻辑3、验证码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部