飞行的猪哼哼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一:自定义路由转换器:
1:在meiduo_mall.utils下创建converters.py转换器:

# 1.converters.py 新建/拖拽以前写好的转换器文件均可
class UsernameConverter:
    """自定义路由转换器去匹配用户名"""
    # 定义匹配用户名的正则表达式
    regex = '[a-zA-Z0-9_-]{5,20}'

    def to_python(self, value):
        return str(value)

    def to_url(self, value):
        return str(value)


class MobileConverter:
    """自定义路由转换器去匹配手机号"""
    # 定义匹配手机号的正则表达式
    regex = '1[3-9]\d{9}'

    def to_python(self, value):
        # to_python:将匹配结果传递到视图内部时使用
        return str(value)

    def to_url(self, value):
        # to_url:将匹配结果用于反向解析传值时使用
        return str(value)

2:在总路由中注册转换器:注意:转换器位置必须在路由列表前面定义。否则路由列表找不到,会报错。
register_converter (转换器类,视图中的别名)

from django.contrib import admin
from django.urls import path, include

# 1.总路由中注册路由转换器
from django.urls import register_converter
from meiduo_mall.utils import converters

register_converter(converters.UsernameConverter, 'username')
register_converter(converters.MobileConverter, 'mobile')

3:子路由使用转换器:

from django.urls import path
from . import views

urlpatterns = [
    # 判断用户名是否重复
    path('usernames/<username:username>/count/',views.UsernameCountView.as_view()),
]

4:查询数据库一般会捕获一下异常并记录日志:

from django import http
from django.views import View

# 注意User的导包路径
from apps.users.models import User 

class UsernameCountView(View):
    """判断用户名是否重复注册"""

    def get(self, request, username):
        '''判断用户名是否重复'''
        # 1.查询username在数据库中的个数
        try:
            count = User.objects.filter(username=username).count()
        except Exception as e:
            return http.JsonResponse({'code':400, 'errmsg':'访问数据库失败'})

        # 2.返回结果(json) ---> code & errmsg & count
        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'count':count})

二:手机号重复注册:
1:视图函数代码:

class MobileCountView(View):

    def get(self, request, mobile):
        '''判断手机号是否重复注册'''
        # 1.查询mobile在mysql中的个数
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            return http.JsonResponse({'code':400, 'errmsg':'查询数据库出错'})

        # 2.返回结果(json)
        return http.JsonResponse({'code':0, 'errmsg':'ok', 'count':count})

2:配置子路由:

 path('mobiles/<mobile:mobile>/count/', views.MobileCountView.as_view()),

三:用户注册接口的实现:
1:视图代码实现:

from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
from .models import User

from meiduo_mall.settings.dev import logger
# Create your views here.

import json
import re
# login函数:把用户信息写入session缓存,并且设置cookie值
from django.contrib.auth import login
# 用户注册
class RegisterView(View):

    def post(self, request):
        # 1、提取参数
        # b'{"username": "xxx"...}' ---> '{"username": "xxx"...}'
        data = request.body.decode()
        # data = {"username": "xxx"...}是一个python字典
        data = json.loads(data)

        # 2、校验参数
        username = data.get('username')
        password = data.get('password')
        password2 = data.get('password2')
        mobile = data.get('mobile')
        sms_code = data.get('sms_code')

        allow = data.get('allow', False)

        # 2.1、必要性校验(是否必传)
        if not all([username, password, password2, mobile, sms_code]):
            # 参数缺失
            return JsonResponse({
                'code': 400,
                'errmsg': "参数缺失",
            }, status=400) # http响应状态码400表示请求参数有误
        # 2.2、单独字段校验
        if not allow:
            return JsonResponse({
                'code': 400,
                'errmsg': '请同意协议'
            })

        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return JsonResponse({
                'code': 400,
                'errmsg': '用户名格式有误!'
            })
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.JsonResponse({'code': 400, 'errmsg': 'password格式有误!'})
        if password != password2:
            return http.JsonResponse({'code': 400, 'errmsg': '两次输入不对!'})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': 'mobile格式有误!'})

        # TODO:将来实现完短信验证码接口之后,此处需要填充验证短信验证码业务

        
        # 3、数据处理——新建用户
        try:    
            user = User.objects.create_user(
                username=username,
                password=password,
                mobile=mobile
            )
        except Exception as e:
            logger.error('用户新建,数据库写入失败')
            return JsonResponse({'code': 400, 'errmsg': '新建用户失败'}, status=500)


        # TODO:当用户注册成功,相当于用户登陆,我们需要记录用户信息 —— 状态保持
        # (1)、把用户数据写入session缓存——redis
        # (2)、在返回当时候,把sessionid设置在浏览器当Cookie中
        login(request, user)

        # 4、构建响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})

注意:.create方法没有加密,.create_user方法是密码加密的。
2:配置子路由:

"""
users应用的子路由模块
"""
from django.urls import re_path,path
from . import views

# 路由表(即使子应用没有任何路径映射,这个表必须存在)
urlpatterns = [
    # 用户注册
    re_path(r'^register/$', views.RegisterView.as_view()),
]

四:用户登录状态保持:
注意:django自定义了login函数,这个函数会把用户信息写入session缓存,并设置cookie值。

from django.contrib.auth import login
 login(request, user)

这里面的user就是这个user = User.objects.create_user,新建的user。
五:生成图片验证:
注意:发送短信验证码的时候需要校验图形验证码是否正确。首先要生成一个图片验证。
因为验证码是个大的模块,所以要新建一个子应用,专门处理验证码的操作。

准备工作:
1:在apps下面新建一个verifications的子应用。
2:在子应用下创建urls.py文件。里面写上urlpatterns=[]。
3:注册子应用:在dev.py中注册子应用。“apps.verifications”
4:在总路由中注册子应用的路由。path("",include(‘apps.verifications.urls’))

5:开启redis.server

图形验证码的逻辑:

在这里插入图片描述
在这里插入图片描述

过程解释:浏览器会发送请求验证码,服务器接收请求(携带一个UUID),提取里面的参数,检查参数,然后生成图片验证码。服务器会把验证码字段保存在redis数据库中,并且UUID就是字段的键。
然后服务器将验证码字段和图片一起返回给浏览器。用户输入后,再次请求时携带UUID,服务器会根据UUID取出验证码字段,然后跟用户输入的字段比较。

代码实现:
1:将第三方包拖入,verifications下的libs下面,(先创建libs),libs存储验证码使用到的第三方库。
2:安装pillow图片库:

pip  install  Pillow  -i https://pypi.tuna.tsinghua.edu.cn/simple

3:约定图片验证码存储在redis的二号库中:在dev中增加配置:

    # 验证码信息: 存到 2 号库
    "verify_code": {  
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://192.168.203.153:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },

4:写视图函数:

from django.shortcuts import render
from django.views import View
from django.http import HttpResponse
from verifications.libs.captcha.captcha import captcha
from django_redis import get_redis_connection
# Create your views here.

# 获取图片验证码
class ImageCodeView(View):

    def get(self, request, uuid):
        # 1、提取参数
        # 2、验证参数
        # 3、数据处理 —— 调用captcha包生成图片验证码,返回图片,并在redis中记录验证码
        # 3.1、使用captcha包获取图片和验证码
        text, image = captcha.generate_captcha()
        # 3.2、把验证码text记录到redis中,key是uuid

        try:
            conn = get_redis_connection('verify_code')
            conn.setex(
                'img_%s'%uuid, # img_fhjeiuw-fewfer-frewfrg
                300, # 300秒有效期
                text # "ABCD"
            )
        except Exception as e:
            print(e)
            return HttpResponse("", status=500)

        # 4、构建响应
        return HttpResponse(
            image, # 图片的字节数据
            content_type='image/jpeg' #
        )

5:写子路由映射:

from django.urls import re_path,path
from . import views

urlpatterns = [
    # 获取图片验证码
    # re_path(r'^image_codes/(?P<uuid>[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12})/$', views.ImageCodeView.as_view()),
    path('image_codes/<uuid:uuid>/', views.ImageCodeView.as_view()),
]
posted on 2020-09-02 22:56  飞行的猪哼哼  阅读(44)  评论(0)    收藏  举报