一:自定义路由转换器:
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()),
]
浙公网安备 33010602011771号