02.meiduomall项目day02学习笔记

1,判断用户名重复注册

  • 目的: 注册的时候, 需要判断用户名是否已经注册过了

  • 分析接口四要素:

    • 1, 路径: /usernames/' + this.username + '/count/
    • 2, 方式: get
    • 3, 请求参数: this.username
    • 4, 响应: count, code
  • 操作流程:

    • 1, 子路由(users/urls.py)

      • url(r'^usernames/(?P<username>\w{5,20})/count/$',views.CheckUsernameView.as_view())
        
    • 2, 类视图(users/views.py)

      • #2, 判断用户名是否存在
        class CheckUsernameView(View):
            def get(self,request,username):
                #1, 根据用户名查询用户数量
                count = User.objects.filter(username=username).count()
        
                #2, 返回响应
                return http.JsonResponse({"count":count,"code":0})
        
    • 3, 放开host.js中的注释(host.js)

      • var host = 'http://127.0.0.1:8000';
        // var host = 'http://www.meiduo.site:8000';
        

2,判断手机号重复注册

  • 目的: 注册的时候可以判断, 手机号是否重复了

  • 操作流程:

    • 1, 子路由(users/urls.py)

      • url(r'^mobiles/(?P<mobile>\d+)/count/$',views.CheckMobileView.as_view()),
        
    • 2, 类视图(users/views.py)

      • #3, 判断手机号是否存在
        class CheckMobileView(View):
            def get(self,request,mobile):
                #1, 根据手机号查询用户数量
                count = User.objects.filter(mobile=mobile).count()
        
                #2, 返回响应
                return http.JsonResponse({"count":count,"code":0})
        

3,图片验证码集成

  • 目的:知道为什么要集成图片验证码, 以及如何集成capture到项目中
  • 操作流程:
    • 作用: 保证安全性, 并且在一定的场景下图片验证码还能分流
    • 集成到项目中: meiduo_mall/libs/captcha
    • 注意点: 需要自己创建libs包

4,verifications应用创建,返回图片

  • 目的: 可以创建子应用,编写获取图片验证码视图

  • 操作流程:

    • 1, 定义图片验证码的redis存储库(dev.py)

      • # redis配置
        CACHES = {
            ...
            "code": {
                "BACKEND": "django_redis.cache.RedisCache",
                "LOCATION": "redis://127.0.0.1:6379/2",
                "OPTIONS": {
                    "CLIENT_CLASS": "django_redis.client.DefaultClient",
                }
            }
        }
        
    • 2, 根路由(meiduo_mall/urls.py)

      • url(r'^', include('verifications.urls')),
        
    • 3, 子路由(verifications/urls.py)

      • from django.conf.urls import url
        from . import views
        
        urlpatterns = [
            url(r'image_codes/(?P<uuid>.+)/',views.ImageCodeView.as_view())
        ]
        
    • 4, 类视图(verifications/views.py)

      • from django.shortcuts import render
        from django.views import View
        from meiduo_mall.libs.captcha.captcha import captcha
        from django import http
        from django_redis import get_redis_connection
        
        #1,获取图片验证码
        class ImageCodeView(View):
            def get(self,request,uuid):
        
                #1, 获取图片验证码, 图片  captcha是外部导入的生成图片验证码功能文件
                _,text,image_data = captcha.generate_captcha()
                #  _,text,image_data 三个参数 第一个是空,第二个text,第三个image_data
                #captcha.generate_captcha() 是captcha.py的启动代码
        
                #2, 存储图片验证码的值到redis中
                redis_conn = get_redis_connection("code")
                redis_conn.set("image_code_%s"%uuid,text,60) #60s为过期时间
        
                #3,返回响应
                return http.HttpResponse(image_data,content_type="image/png")
        
      • 5, 前端的图片标签,添加点击事件(register.html)

    •  <img :src="image_code_url" alt="图形验证码" class="pic_code" @click="generate_image_code">
      
    • 6, 存储图片验证码的值到redis中,需要启动redis,本机已安装,启动文件目录E:\Redis\redis-cli.exe 双击运行即可

      • 基本命令
         select 2   //2 为存储的库 当前信息存储的是哪个库就切换到哪个库
         keys *     //查看所有存储的信息
        

6,短信验证码分析,实现

  • 目的: 可以编写短信验证码后端逻辑

  • 操作流程:

    • 1, 子路由(verifications/urls.py)

      • url(r'sms_codes/(?P<mobile>\d+)/',views.SMSCodeView.as_view()),
        
    • 2, 类视图(verifications/views.py)

      • #2,获取短信验证码
        class SMSCodeView(View):
            def get(self,request,mobile):
                #1,获取参数
                image_code = request.GET.get("image_code")
                image_code_id = request.GET.get("image_code_id")
        
                #2,校验参数
                #2,1 为空检验
                if not all([image_code,image_code_id]):
                    return http.JsonResponse({"code":4001,"errmsg":"参数不全"})
        
                #2,1 手机号格式
                if not re.match(r'^1[3-9]\d{9}$',mobile):
                    return http.JsonResponse({"code": 4001,"errmsg":"手机号格式有误"})
        
                #2,2 图片验证码正确性
                redis_conn = get_redis_connection("code")
                redis_image_code = redis_conn.get("image_code_%s"%image_code_id)
        
                if image_code != redis_image_code.decode():
                    return http.JsonResponse({"code": 4001, "errmsg": "图片验证码错误"})
        
                #3,发送短信,数据入库
                sms_code = "%06d"%random.randint(0,999999)
                print("sms_code = %s"%sms_code)
        
                #4,返回响应
                return http.JsonResponse({"code":0})
        

7,云通讯

  • 目的: 可以集成云通讯发送短信
  • 使用流程:
    • 1, 注册账号,实名认证
    • 2, 下载包
    • 3, 导入项目中(libs)
    • 4, 测试发送
      • 需要将自己的应用信息填写到sms.py中
      • _accountSid, _accountToken, _appId
    • 注意点:
      • 发送的手机号, 需要先添加为测试账号

8,短信验证码实现

  • 目的: 可以将短信发送的过程集成到项目中

  • 操作流程:

    • 1, 类视图(verifications/views.py)

      • #2,获取短信验证码
        class SMSCodeView(View):
            def get(self,request,mobile):
               ....
        
                #3,发送短信,数据入库
                sms_code = "%06d"%random.randint(0,999999)
                print("sms_code = %s"%sms_code)
                result = CCP().send_template_sms(mobile, [sms_code, 5], 1)
        
                #3,1 判断是否发送成功
                if result == -1:
                    return http.JsonResponse({"code": 4001, "errmsg": "短信发送失败"})
        
                # 3,2 保存短信验证码到redis,方便之后判断短信的正确性
                redis_conn.set("sms_code_%s"%mobile,sms_code,300)
        
                #4,返回响应
                ...
        

9,短信验证码校验

  • 目的: 可以在注册接口中判断短信验证码的正确性, 并且可以对密码加密

  • 操作流程:

    • 1, 类视图(users/views.py)

      • class RegisterView(View):
            def get(self,request):
                return render(request,'register.html')
        
            def post(self,request):
                ...
        
                #2,5 短信验证码正确
                redis_conn = get_redis_connection("code")
                redis_sms_code = redis_conn.get("sms_code_%s"%phone)
                if msg_code != redis_sms_code.decode():
                    return http.HttpResponseForbidden("短信验证码填写错误")
        
                #2,6 协议需要同意
                ...
        
                #3, 数据入库
                # user = User.objects.create(username=user_name,password=pwd,mobile=phone)
                # 可以对密码加密
                user = User.objects.create_user(username=user_name,password=pwd,mobile=phone)
        
                #4, 返回响应
                return redirect('/')
        

10,短信验证码频繁

  • 目的: 可以设置标记, 解决短信频繁发送的问题

  • 操作流程:

    • 1, 类视图(users/views.py)

      • #2,获取短信验证码
        class SMSCodeView(View):
            def get(self,request,mobile):
                #1,获取参数
                ...
        
                #1,1 判断标记是否过期
                redis_conn = get_redis_connection("code")
                send_flag = redis_conn.get("send_flag_%s"%mobile)
                if send_flag:
                    return http.JsonResponse({"code": 4001, "errmsg": "短信频繁发送"},status=400)
        
                ...
               
        
                #3,1 设置标记,防止1分钟之内, 短信多次发送
                redis_conn.set("send_flag_%s"%mobile,1,60)
        
        
        

11,pipeline操作redis

  • 目的: 可以通过pipeline(管道)操作redis

  • 操作流程:

    • 1, 进入到命令调试窗口

      • python manager.py shell
    • 2, 测试pipeline

      • In [1]: from django_redis import get_redis_connection                                                                                                              
        
        In [2]: redis_conn = get_redis_connection("default")                                                                                                               
        
        In [3]: redis_conn.set("name","banzhang")                                                                                                                          
        Out[3]: True
        
        In [4]: redis_conn.set("age",13)                                                                                                                                   
        Out[4]: True
        
        In [5]: #1, 设置管道                                                                                                                                               
        
        In [6]: pipeline = redis_conn.pipeline()                                                                                                                           
        
        In [7]: pipeline.set("name","banzhang")                                                                                                                            
        Out[7]: StrictPipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=1>>>
        
        In [8]: pipeline.set("age",13)                                                                                                                                     
        Out[8]: StrictPipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=1>>>
        
        In [9]: #2, 提交管道                                                                                                                                               
        
        In [10]: pipeline.execute()                                                                                                                                        
        Out[10]: [True, True]
        
        In [11]:  
        
        

12,celery介绍

  • 目的: 知道celery的作用和组成即可
  • 作用: 处理耗时任务, 比如: 发短信,发邮件, 发视频, 上传图片等等
  • 组成:
    • image-20200112122040390

13,celery测试

  • 目的: 可以参考celery官方文档, 测试celery的运行

  • 操作流程:

    • 1, 创建celery_tasks包, 编写celery.py模块(celery_tasks/celery.py)

      • from __future__ import absolute_import, unicode_literals
        import os
        from celery import Celery
        
        #1, 加载项目环境
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings.dev")
        
        #2, 创建celery对象
        app = Celery('meiduo_mall')
        
        #3, 加载配置
        app.config_from_object('celery_tasks.config', namespace='CELERY')
        
        #4, 自动注册任务
        app.autodiscover_tasks()
        
        #5, 手动添加任务
        @app.task(bind=True)
        def debug_task(self):
            print("debug_task....")
        
        # 启动celery:  celery -A proj worker -l info
        # 发送任务: 任务名称.delay(参数)
        
    • 2, 创建配置文件config.py

      • #1, 任务队列
        broker_url = 'redis://127.0.0.1:6379/14'
        
        #2, 结果队列
        result_backend = 'redis://127.0.0.1:6379/15'
        
    • 3, 启动, 发送任务

      • 终端启动celery: celery -A celery_tasks.celery worker -l info

      • 注意:celery不支持在windows下运行任务,需要借助eventlet来完成。先安装 pip install eventlet

      • 终端启动celery -A celery_tasks.celery worker -l info -P eventlet  -c 10
        
      • 参考文档https://www.cnblogs.com/qumogu/p/13284173.html

      • 发送任务: 任务名称.delay(参数)

        • 需要先进入到python manage.py shell中

        • (venv) E:\python工程\meiduo_mall\day01\meiduo\meiduomall>python manage.py shell
          Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
          Type "help", "copyright", "credits" or "license" for more information.
          (InteractiveConsole)
          >>> from celery_tasks.celery import debug_task
          >>> debug_task.delay()
          <AsyncResult: 8fac965e-ffb0-4a75-8907-068bc5bdda7c>
          
          

14, 使用包的形式封装test任务

  • 目的: 可以创建包, 并注册添加到celery并测试使用

  • 操作流程:

    • 1, 定义test包,创建tasks.py文件(celery_tasks/test/tasks.py)

      • from celery_tasks.celery import app
        
        @app.task(bind=True)
        def sum(self,num1,num2):
            return num1 + num2
        
    • 2, 添加到celery(celery_tasks/celery.py)

      • app.autodiscover_tasks(['celery_tasks.test'])
        
    • 3, 测试使用

      • 启动: celery -A celery_tasks.celery worker -l info -P eventlet -c 10

      • 发送任务:

        • In [1]: from celery_tasks.test.tasks import sum                                                                                                                    
          
          In [2]: result = sum.delay(10,20)                                                                                                                                  
          
          In [3]: result.get()                                                                                                                                               
          Out[3]: 30
          
          

15,celery短信发送

  • 目的: 操作流程:(失败,在send_message中不调用发送短信的代码)

    • 1, 创建短信发送任务包(celery_tasks/sms/tasks.py)

      • from celery_tasks.celery import app
        from meiduo_mall.libs.yuntongxun.sms import CCP
        
        
        @app.task(bind=True)
        def send_message(self,mobile,sms_code):
        
            import time
            time.sleep(10)
        
            result = CCP().send_template_sms(mobile, [sms_code, 5], 1)
        
        
        
    • 2, 类视图(verifications/views.py)

      • class SMSCodeView(View):
            def get(self,request,mobile):
        			
              	...
        
                if not redis_image_code:
                    return http.JsonResponse({"code": 4001, "errmsg": "图片验证码已过期"})
        
                ...
                #使用celery发送短信
                from celery_tasks.sms.tasks import send_message
                send_message.delay(mobile,sms_code)
        
        				...
        

16,发送短信重试

  • 目的: 可以通过retry方法重试发送短信

  • 操作流程:

    • 1, sms包的任务更改(celery_tasks/sms/tasks.py)

      • from celery_tasks.celery import app
        from meiduo_mall.libs.yuntongxun.sms import CCP
        
        
        @app.task(bind=True)
        def send_message(self,mobile,sms_code):
            #测试耗时
            # import time
            # time.sleep(10)
        
            #1, 发送短信
            try:
                result = CCP().send_template_sms(mobile, [sms_code, 5], 1)
            except Exception as e:
                result = -1
        
            #2,判断是否发送成功
            if result == -1:
                #重试, exc: 发送短信失败报的异常,  countdown: 间隔几秒重试, max_retries:重试的次数
                self.retry(exc=Exception("发送短信失败"),countdown=5,max_retries=3)
        
        

17,用户登陆分析

  • 目的: 理解登录流程,和接口四要素
  • 接口四要素分析:
    • 1,请求地址: /login
    • 2, 请求方式: post
    • 3, 请求参数: username, pwd, remembered
    • 4, 返回响应: 重定向首页

18,登陆实现

  • 目的: 可以使用authentication方法实现用户, 认证登录

  • 操作流程:

    • 1, 子路由(users/urls.py)

      •    url(r'^login/$',views.LoginView.as_view()),
        
    • 2, 类视图(users/views.py)

      • #4, 登录视图
        class LoginView(View):
            def get(self,request):
                return render(request,'login.html')
        
            def post(self,request):
                #1,获取参数
                username = request.POST.get("username")
                pwd = request.POST.get("pwd")
                remembered = request.POST.get("remembered")
        
                #2,校验参数
                #2,1 为空校验
                if not all([username,pwd]):
                    return http.HttpResponseForbidden("参数不全")
        
                #2,2 用户名格式
                if not re.match(r'^[a-zA-Z0-9_-]{5,20}$',username):
                    return http.HttpResponseForbidden("用户名格式不对")
        
                #2,3 密码格式校验
                if not re.match(r'^[0-9A-Za-z]{8,20}$',pwd):
                    return http.HttpResponseForbidden("密码格式不对")
        
                #2,4 账号密码正确性校验, 如果认证成功返回用户对象, 不成功返回None
                user = authenticate(request, username=username, password=pwd)
        
                if not user:
                    return http.HttpResponseForbidden("账号或者密码不正确")
        
                #3,数据入库(状态保持)
        
        
                #4,返回响应
                return redirect("/")
        

19,登陆状态保持实现

  • 目的: 可以通过系统方法login, 实现状态保持

  • 操作流程:

    • 1, 类视图(users/views.py)

      • class LoginView(View):
          	def get(..)
            	...
              
             def post(..)
            		...
            	  #3,数据入库(状态保持)
                login(request, user) # 就是将用户的信息存储在session
                if remembered == "on":  #如果用户在前端选择记住密码
                    request.session.set_expiry(3600*24*2) #保存两天
                else:
                    request.session.set_expiry(0) #一次浏览器会话结束
        				...
        

20,多账号登陆

  • 目的: 可以重写系统类的方法, 实现多账号登录(即支持用户名登录也支持手机号登录)

  • 操作流程:

    • 1, 自定义类,重写authenticate方法(meiduo_mall/utils/my_authenticate.py)

      • from django.contrib.auth.backends import ModelBackend
        import re
        from users.models import User
        
        #1, 重写系统认证方法
        class MyModelBackend(ModelBackend):
            def authenticate(self, request, username=None, password=None, **kwargs):
        
                #1, 根据username查询用户
                try:
                    if re.match(r'^1[3-9]\d{9}$',username):
                        user = User.objects.get(mobile=username)
                    else:
                        user = User.objects.get(username=username)
                except Exception as e:
                    return None
        
                #2, 校验密码
                if user.check_password(password):
                    return user
                else:
                    return None
        
    • 2, 设置自定义认证类(dev.py)

      • 
        # 设置自定义认证方法
        AUTHENTICATION_BACKENDS = ['meiduo_mall.utils.my_authenticate.MyModelBackend']
        
posted @   CodeMan-k23  阅读(54)  评论(0编辑  收藏  举报
编辑推荐:
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?
点击右上角即可分享
微信分享提示