一、创建用户模型
from django.db import modelsfrom django.contrib.auth.models import AbstractUserclass User(AbstractUser):mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')class Meta:db_table = 'tb_users'verbose_name = '用户'verbose_name_plural = verbose_namedef __str__(self):return self.username
在settings.py文件中指定用户模型类(AUTH_USER_MODEL = ‘app应用名.模型类名’)
AUTH_USER_MODEL = 'users.User'
二、用户注册接口
from django.http import JsonResponsefrom django.views import Viewfrom .models import Userimport logginglogger = logging.getLogger('django')# 验证用户名重复class UsernameCountView(View):def get(self, request, username):try:# 1、统计用户数量count = User.objects.filter(username=username).count()except Exception as e:print(e)# 写日志logger.error(e)# 2、构建响应返回return JsonResponse({'code': 0,'errmsg': 'ok','count': count})
from django.urls import path, re_pathfrom users.views import *urlpatterns = [re_path(r'^usernames/(?P<username>[a-zA-Z0-9_-]{5,20})/count/$', UsernameCountView.as_view()),re_path(r'^mobiles/(?P<mobile>1[3-9]\d{9})/count/$', MobileCountView.as_view()),]
# 保存后端API服务器地址,视情况而定var host = 'http://127.0.0.1:8000';
http://IP:8000/usernames/用户名/count/
三、手机号验证接口
class MobileCountView(View):def get(self, request, mobile):try:count = User.objects.filter(mobile=mobile).count()except Exception as e:print(e)logger.error(e)return JsonResponse({'code': 0,'errmsg': 'ok','count': count})
re_path(r'^mobiles/(?P<mobile>1[3-9]\d{9})/count/$', MobileCountView.as_view()),
http://IP:8000/mobiles/手机号/count/
四、解决跨域问题
# 1.安装pip install django-cors-headers# 2.INSTALLED_APPS注册'corsheaders',# 3.添加MIDDLEWARE'corsheaders.middleware.CorsMiddleware',# 4.setting.py新增CORS_ORIGIN_WHITELIST = ['http://127.0.0.1','http://127.0.0.1:80',]# 允许在不同主机之间传递cookie数据CORS_ALLOW_CREDENTIALS = True
五、图形验证码
# 1.新建app verifications# 2.安装pillow pip install pillow# 3.项目目录下创建lib的python包导入文件# 4.配置Redis缓存"verify_code": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://82.156.189.83:6379/2","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},"sms_code": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://82.156.189.83:6379/3","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",}},# 5.
from django.views import View # 从django.views导入Viewfrom libs.captcha.captcha import captcha # 导入第三方包captchafrom django_redis import get_redis_connection # 导入redis库from django.http import HttpResponse # 导入HttpResponse给前端进行响应import logging # 导入日记模块logger = logging.getLogger('django')# 图形验证码接口class ImageCodeView(View):def get(self, request, uuid):# 1、调用库生成图形验证码text, image = captcha.generate_captcha()# 2、存储redisconn = get_redis_connection('verify_code')try:# 验证码写入redisconn.setex("img_%s" % uuid,300,text)except Exception as e:print(e)logger.error(e)# 3、构建响应return HttpResponse(image, content_type='image/jpg')
from django.urls import re_path # 从django.urls导入re_pathfrom . import views # 从当前文件夹,导入viewsurlpatterns = [# 图形验证码re_path(r'^image_codes/(?P<uuid>[\w-]+)/$', views.ImageCodeView.as_view()),]
六、短信验证码
# 1.# ACCOUNT SID_accountSid = ''# AUTH TOKEN_accountToken = ''# AppID_appId = ''# 2.if __name__ == '__main__':# 注意: 测试的短信模板编号为1CCP().send_template_sms('测试手机号', ['1234', 5], 1)# 3.
from django.http import HttpResponse,JsonResponsefrom aerf_mall.libs.yuntongxun.ccp_sms import CCPimport randomimport reclass SMSCodeView(View):def get(self, request, mobile):# 1、提取参数image_code = request.GET.get('image_code')uuid = request.GET.get('image_code_id')# 2、校验参数if not all([image_code, uuid]):return JsonResponse({'code': 400,'errmsg': '缺少必要参数'}, status=400)if not re.match(r'^\w{4}$', image_code):return JsonResponse({'code': 400,'errmsg': '图片验证码格式不符'}, status=400)if not re.match(r'^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$', uuid):return JsonResponse({'code': 400,'errmsg': 'uuid格式不符'}, status=400)# 3、校验redis中的图片验证码是否一致——业务层面上的校验conn = get_redis_connection('verify_code')# 3.1 提取redis中存储的图片验证码# get(): b"YBCF"image_code_from_redis = conn.get("img_%s"%uuid)# 如果从redis中读出的验证码是空;if not image_code_from_redis:return JsonResponse({'code':400, 'errmsg': '验证码过期'}, status=400)# 如果读出来的不是空,我们要删除该验证码image_code_from_redis = image_code_from_redis.decode()conn.delete("img_%s"%uuid)# 3.2 比对(忽略大小写)if image_code.lower() != image_code_from_redis.lower():return JsonResponse({'code': 400,'errmsg': '图形验证码输入错误'}, status=400)# 4、发送短信验证码conn = get_redis_connection('sms_code')# 判断60秒之内,是否发送过短信——判断标志信息是否存在flag = conn.get('flag_%s'%mobile)if flag:return JsonResponse({'code':400, 'errmsg':'请勿重复发送短信'}, status=400)# 构建6位手机验证码sms_code = "%06d"%random.randint(0, 999999)print("手机验证码:", sms_code)# 生成一个redis的pipeline对象p = conn.pipeline()# 把验证码存入redisp.setex("sms_%s"%mobile,300,sms_code)# 一旦用户发送了短信,需要在redis中存储一个标志p.setex("flag_%s"%mobile,60,'1')p.execute() # 批量执行队列中的指令# 发送验证码# 同步调用——只有当该发送短信当函数执行完毕,且返回了;代码才会继续往后执行!# 如果网络出现了问题,该函数就会一致阻塞在此,导致我们的视图函数无法即使响应!CCP().send_template_sms(mobile, [sms_code, 5], 1)return JsonResponse({'code': 0,'errmsg': 'ok'})
from django.urls import re_pathfrom . import viewsurlpatterns = [re_path(r'^sms_codes/(?P<mobile>1[3-9]\d{9})/$', views.SMSCodeView.as_view()),]
七、异步方案Celery
# 1.安装Celerypip install -U Celery# 2.项目目录下创建celery_tasks的python包# 3.在celery_tasks下创建config.py和main.py文件# 4.config.py# 如果使用 redis 作为中间人# 需要这样配置:# 1、将来生产者会把任务发不到redis的10号库# 2、消费者会从redis的10号库中提取任务并执行broker_url='redis://127.0.0.1:6379/10'# 5.main.py"""该文件作为异步应用程序初始化的模块"""# 在异步任务程序中加载django的环境import osos.environ.setdefault('DJANGO_SETTINGS_MODULE','aerf_test.settings.dev' # 此行aerf_test要改成你对应的项目名字)from celery import Celery# 初始化一个应用程序对象(名称可以任意填写)app = Celery("aerf")# 加载配置文件——参数是配置文件(模块)的导包路径# 我们将来是在celery_tasks包所在的目录为工作目录运行异步程序;app.config_from_object('celery_tasks.config')# 告知app监听的任务有哪些# 该函数的参数是一个列表,列表里写的是任务包的导包路径app.autodiscover_tasks(['celery_tasks.sms',])# 6.在celery_tasks下创建sms的python包# 7.将云通讯目录拷贝到celery_tasks下# 8.在sms下创建tasks.py文件"""tasks.py文件名是固定,该文件中定义异步任务函数!!"""from celery_tasks.main import appfrom celery_tasks.yuntongxun.ccp_sms import CCP# 定义一个发送短信的任务函数# name自定义任务函数名称# 被app.task装饰的函数就是异步任务函数@app.task(name='ccp_send_sms_code')def ccp_send_sms_code(mobile, sms_code):return CCP().send_template_sms(mobile, [sms_code, 5], 1)# 9.修改View的视图from celery_tasks.sms.tasks import ccp_send_sms_codeccp_send_sms_code.delay(mobile, sms_code)# 10.启用celery服务celery -A celery_tasks.main worker -l infocelery -A celery_tasks.main worker -l info -c 10
八、用户注册
from django_redis import get_redis_connectionfrom django.contrib.auth import loginimport jsonimport reclass RegisterView(View):def post(self, request):# 1、提取参数# request.body --> b'{"username": "xxxx"}'# request.body.decode() --> '{"username": "xxxx"}'data = json.loads(request.body.decode())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')# 2、校验参数if not all([username, password, password2, mobile, sms_code]):return JsonResponse({'code':400, 'errmsg': '缺少参数'}, status=400)if not re.match(r'^\w{5,20}$', username):return JsonResponse({'code':400, 'errmsg': '用户名格式有误'}, status=400)if not re.match(r'^\w{8,20}$', password):return JsonResponse({'code':400, 'errmsg': '密码格式有误'}, status=400)if password != password2:return JsonResponse({'code':400, 'errmsg': '密码输入不一致!'}, status=400)if not re.match(r'^\d{6}$', sms_code):return JsonResponse({'code': 400, 'errmsg': '验证码格式有误'}, status=400)if not allow:return JsonResponse({'code': 400, 'errmsg': '请求统一用户协议!'}, status=400)# 手机验证码校验conn = get_redis_connection('sms_code')sms_code_from_redis = conn.get('sms_%s'%mobile)if not sms_code_from_redis:return JsonResponse({'code': 400, 'errmsg': '短信验证码过期!'}, status=400)sms_code_from_redis = sms_code_from_redis.decode()if sms_code_from_redis != sms_code:return JsonResponse({'code':400, 'errmsg': '短信验证码有误!'}, status=400)# 3、新建数据,构建用户模型类对象保存数据库# User.objects.create() --> 构建的用户模型类对象,密码不会加密# User.objects.create_user() --> 构建用户模型类对象,把明文密码加密# User.objects.create_superuser() --> 构建用户模型类对象,把明文密码加密以及is_staff=Truetry:user = User.objects.create_user(username=username,password=password,mobile=mobile)except Exception as e:print(e)# 传入request对象和user对象,把用户信息写入session缓存(redis)中,并且把sessionid返回给浏览器# 存入cookielogin(request, user)# 4、构建响应response = JsonResponse({'code': 0, 'errmsg':' ok'})response.set_cookie('username',username,max_age=3600*24*14)return response
re_path(r'^register/$', RegisterView.as_view()),
