Django项目实践(商城):三、用户注册(后端开发)

在这里插入图片描述

(根据居然老师直播课内容整理)

一、用户注册业务逻辑分析

在这里插入图片描述

  • 用户输入地址后,获取注册页面
    在这里插入图片描述
  • 用户输入用户名,前端应检查此用户名是否注册过;
  • 两次密码必须输入一致,否则前端应控制重新输入
  • 前端会验证手机号码是否答合规范
  • 图形验证码会进行验证,正确后,获取短信验证码才应生效
  • 短信验证码都正确后,才能提交注册
  • 以上都正确后,后端才会进行处理注册请求
  • 注册请求通过form表单POST发送数据到后端
  • 注册视图接收请求后,接收数据
  • 校验数据,如果数据有误或不符合规范,直接返回到登录界面,并发送错误信息
  • 数据校验无误后,将保存数据:数据保存到mysql数据库中
    • 保存用户名、密码(加密后的)、手机号等信息
  • 将状态保存到session中
    • 将session 信息中保存到redis中
  • 将注册结果返回到前端

二、用户注册接口设计和定义

1、设计接口基本思路

  • 对于接口的设计,我们要根据具体的业务逻辑,设计出适合业务逻辑的接口。
  • 设计接口的思路:

1.1 分析要实现的业务逻辑:

  • 明确在这个业务中涉及到几个相关子业务。
  • 将每个子业务当做一个接口来设计。

1.2 分析接口的功能任务,明确接口的访问方式与返回数据:

  • 请求方法(如GET、POST、PUT、DELETE等)。
  • 请求地址。
  • 请求参数(如路径参数、查询字符串、表单、JSON等)。
  • 响应数据(如HTML、JSON等)。

2、用户注册接口设计

  • 用户注册这个业务可能涉及以下几个子业务
    • 用户名是否注册过
    • 图形验证码是否正确
    • 发送手机验证码
    • 用户正常注册
  • 下面着重介绍用户正常注册这个子业务接口设计

2.1 请求方式

选项 方案
请求方法 POST
请求地址 /register/

2.2 请求参数:表单参数

参数名 类型 是否必传 说明
username string 用户名
password string 密码
password2 string 确认密码
mobile string 手机号
sms_code string 短信验证码
allow string 是否同意用户协议

2.3 响应结果

响应结果 响应内容
注册失败 响应错误提示
注册成功 重定向到首页

3、用户注册接口实现

3.1 用户注册接口定义

# ./apps/users/views.py
from django.shortcuts import render
from django.views import View


class RegisterView(View):
    """用户注册"""

    def get(self,request):
        """提供用户注册页面"""
        return render(request, 'register.html')

    def post(self,request):
        """提供用户注册逻辑"""

        # 接收数据及数据校验 
        pass

3.2 定义校验处理类

  • 在./apps/users下定义forms.py,对需要校验的数据进行校验处理
  • 对数据进行简单校验:变量名(传递的参数名)=form.CharField(简单校验类型=标准值,错误信息字典)
    • 用户名、密码、确认密码、手机对最大长度、最小长度、是否必填进行校验
    • 用户名和手机号存在的校验,可以前端用ajax方式校验,此处就不处理
    • 图形验证码:不需要校验,图形验证码正确后,才能发送短信验证,否则无法发送短信验证码
    • 短信验证码:此片只进行长度和必填进行简单校验,有专门的校验算法判断短信验证码的正确性
  • 定义clean(self)函数,扩展数据校验
    • 首先调用 基类本身的clean(self)校验函数:cleaned_data = super().clean()
    • 再判断两次密码是否一致,
      • 如果不一致,抛出异常
# ./apps/users/form.py
from django import forms

class RegisterForm(forms.Form):
    # 变量名:必须前端传递参数一致
    # max_length:限制最大长度
    # min_length:限制最小长度
    # required:True,必须填写
    # error_message:错误信息,字典类型,key是前面对应的限制条件,value是对应的错误信息
    username=forms.CharField(max_length=20,min_length=5,required=True,error_messages={
    
    "max_length": "用户名长度最长为20", "min_length": "用户名最少长度为5","required":"用户名必须填写"})
    password = forms.CharField(max_length=20, min_length=8, required=True,error_messages={
    
    "max_length": "密码长度最长为20", "min_length": "密码最少长度为8","required":"密码必须填写"})
    password2 = forms.CharField(max_length=20, min_length=8, required=True,error_messages={
    
    "max_length": "确认密码长度最长为20", "min_length": "确认密码最少长度为8","required":"确认密码必须填写"})
    mobile = forms.CharField(max_length=11, min_length=11, required=True,error_messages={
    
    "max_length": "手机长度最长为20", "min_length": "手机最少长度为11","required":"手机必须填写"})
    sms_code = forms.CharField(max_length=6, min_length=6, required=True,error_messages={
    
    "max_length": "手机长度最长为6", "min_length": "手机最少长度为6","required":"短信验证码必须填写"})

    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        password2 = cleaned_data.get('password2')

        if password != password2:
            raise forms.ValidationError('两次密码不一致')
        return cleaned_data

3.3 用户注册接口开发

  • 接收并校验参数:实例化校验处理类
  • 判断校验结果
  • 如果校验无误:
    • 取出 用户名、密码、手机号
    • 保存注册信息到数据库:利用Django提供的用户模型类方法
    • 状态保持(暂时不写)
    • 重定向返回到首页
  • 如果校验有误:
    • 取出校验错误信息,生成待返回格式的错误信息
    • 返回到注册页面(或首页)
from django.shortcuts import render
from django.views import View
from .forms import RegisterForm
# from .models import User
from users.models import User
from django import http


class RegisterView(View):
    """用户注册"""

    def get(self,request):
        """提供用户注册页面"""
        return render(request, 'register.html')

    def post(self,request):
        """提供用户注册逻辑"""

        # 校验参数
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            username = register_form.cleaned_data.get('username')
            password = register_form.cleaned_data.get('password')
            mobile = register_form.cleaned_data.get('mobile')

            # 保存到数据库中
            try:
                User.objects.create_user(username=username, password=password, mobile=mobile)
            except Exception as e:
                return render(request, 'register.html', {
    
    'register_errmsg': '注册失败'})

                # 状态保持

                # 响应结果
                return http.HttpResponse('注册成功, 重定向到首页')
                # return redirect(reverse('contents:index'))
            else:
                print(register_form.errors.get_json_data())
                context = {
    
    
                    'forms_errors': register_form.errors
                }
                return render(request, 'register.html', context=context)

3.4 此处一异常处理

3.4.1 错误信息描述:

如果出现下面错误信息在这里插入图片描述

3.4.2解决方法:

需要检查导包路径

  • 将 from .models import User 改为 from users.models import User
  • 同时将lgshop 改为 Scoures Root
    在这里插入图片描述

在这里插入图片描述

3.4.3 解决方法二:

  • ./lgshop/urls.py
    在这里插入图片描述
    在这里插入图片描述

3.5 保存注册数据

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

3.6 响应注册结果

  • 注册成功,重定向到首页(前提是定义首页,步骤如下)
    • 创建首页contents应用
    • 编写index.html
    • 写view方法
    • 注册contents应用
      在这里插入图片描述

3.7 状态保持

  • 如果需求是注册成功后即表示用户登入成功,那么此时可以在注册成功后实现状态保持
  • 如果需求是注册成功后不表示用户登入成功,那么此时不用在注册成功后实现状态保持
  • 状态保持:将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前浏览器的 cookie 和服务端的 session 中。

3.7.1 Django的login()方法(状态保持)

  • Django用户认证系统提供了login()方法:封装了写入session的操作,帮助我们快速登入一个用户,并实现状态保持。
  • login()位置:django.contrib.auth.init.py文件中。

3.7.2 状态保持 session 数据存储的位置

  • session保存在Redis数据库的1号库
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

在这里插入图片描述

三、用户重复注册验证(后端)

1、用户名重复注册逻辑分析

  • 用户注册时,当全部信息输入完成提交后,再告诉用户已经被注册过了,这样的用户体验不友好
  • 所以,需要用户名输入框失去焦点且简单验证正确后,向后台发送用户重复注册校验请求,如果重复校验提示用户名已被注册过,需要更换,如果没有注册,什么都不提示
  • 这个操作采用ajax进行异步操作即可,提高用户体验
    在这里插入图片描述

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

2.1 请求方式

选项 方案
请求方法 GET
请求地址 /usernames/(?P[a-zA-Z0-9_-]{5,20})/count/

2.2 请求参数:路径参数

参数名 类型 是否必传 说明
username string 用户名

2.3 响应结果:JSON

响应结果 响应内容
code 状态码
errmsg 错误信息
count 记录该用户名的个数

3、后台实现

  • 用户名重复注册返回不是html,只需返回一个json就行了

3.1 定义view方法

  • 用户名重复注册校验 不应该 用户注册业务里实现,同时接口也不一样,所以在users.view.py 再定义一个UsernameCountView类
  • UsernameCountView类只需一个get方法
  • 只需要统计一下数据库中有几个username即可,应该只有一个或没有
  • 所以,取到数据后,直接返回即可
  • 注意:数据模型中用的user基类是django的用户类,注意使用方法
    在这里插入图片描述
# ./apps/users/views.py
class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self,request,username):
        """
                :param username: 用户名
                :return: 返回用户名是否重复  JSON
                """
        try:
            count = User.objects.filter(username=username).count()
            return http.JsonResponse({
    
    'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})
        except Exception as e:
            logging.error(e)
            return http.JsonResponse({
    
    'code': RETCODE.DBERR, 'errmsg': '数据访问失败', 'count': -1})

3.2 注册路由

在这里插入图片描述

re_path(r"^usernames/(?P<username>[a-zA-Z0-9-_]{5,20}/count/$)", views.UsernameCountView.as_view())

猜你喜欢

转载自blog.csdn.net/laoluobo76/article/details/113095002