1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Django搭建服务器 和微信小程序通信 验证码存入redis 用户信息存入mysql以及图片上传

Django搭建服务器 和微信小程序通信 验证码存入redis 用户信息存入mysql以及图片上传

时间:2023-06-05 17:23:10

相关推荐

Django搭建服务器 和微信小程序通信 验证码存入redis 用户信息存入mysql以及图片上传

写在前面:整体是实现小程序的登录和注册,并接收验证码进行校验。

一、创建项目

django-admin startproject wxTest

二、注册app,进入到wxTest目录中

python manage.py startapp api

三、提前安装djangorestframework包

四、在settings.py中添加rest_framework

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework','api.apps.ApiConfig']# 用户信息存入mysql的wx数据库DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'wx', # 数据库名字可更改'PORT':'3306','USER':'root','PASSWORD':'123456','HOST':'localhost'}}# 如果需要用到django-redis,需要添加CACHES = {'default': {'BACKEND': 'django_redis.cache.RedisCache','LOCATION': 'redis://127.0.0.1:6379',"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient","CONNECTION_POOL_KWARGS":{"max_connections":100}# "PASSWORD": "yoursecret",},},}# ---->设置上传文件的目录和外部访问的路径MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')MEDIA_URL = '/media/'

五、wxTest\urls.py中

from django.contrib import adminfrom django.urls import path,includefrom django.conf.urls import urlfrom django.views.static import servefrom django.conf import settingsfrom django.conf.urls.static import staticurlpatterns = [path('admin/', admin.site.urls),path('api/', include('api.urls')),# 添加这行——————允许所有的media文件被访问url(r'media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),]# 或者以下方法# 添加这行——————允许所有的media文件被访问# urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

六、wxTest\api\models.py中

from django.db import modelsclass UserInfo(models.Model):id = models.AutoField(primary_key=True)# unique唯一phone = models.CharField(max_length=11,verbose_name='手机号',unique=True)# 用户登录后唯一标识# null=True, 表示数据库的该字段可以为空# blank=True,表示你的表单填写该字段的时候可以不填token = models.CharField(max_length=64,verbose_name='用户Token',null=True,blank=True)

终端输入:pythonmanage.pymakemigrations(生成迁移文件)

终端输入:pythonmanage.pymigrate(将结构变化应用到数据库)

七、wxTest\api\views.py中

import osimport reimport randomimport uuidimport chardetfrom django.http import JsonResponsefrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom django_redis import get_redis_connectionfrom . import modelsfrom django.conf import settingsclass DelView(APIView):'''删除本地图片功能'''def get(self, request, *args, **kwargs):# 传入的文件路径列表http://127.0.0.1:8000/media/1f75e5dfcf258de22566433799ce67a1.jpgimagePath = request.query_params.get('image', '')MEDIA_ROOT = settings.MEDIA_ROOTtry:imagePath = imagePath.split("/")[-1]file_path = os.path.join(os.getcwd(),MEDIA_ROOT + imagePath)file_path = file_path.replace('/','\\')os.remove(file_path)return Response({"status": True, "message": "图片删除成功"})except Exception as e:return Response({"status": False, "message": "图片删除失败:"+str(e)})# 传图功能class UploadView(APIView):'''上传图片功能'''def post(self, request, *args, **kwargs):# 传入的文件路径列表imageList = request.FILES.get('image', '')# imageList = request.FILES['image']# 文件类型,可以判断如果不是图片格式则不上传file_type = os.path.splitext(imageList.name)[1]if not imageList:print("上传文件不能为空")return JsonResponse({"status": False, "message": "上传文件不能为空"})file_format = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.webp', '.tif', '.tiff']if file_type.lower() not in file_format:print("上传文件类型非图片格式")return JsonResponse({"status": False, "message": "上传文件类型非图片格式"})# 获得一个唯一名字:uuid +hashnew_name = self.get_random_str()# 组合成文件新名字new_file_name = new_name + file_typeMEDIA_ROOT = settings.MEDIA_ROOTif not os.path.exists(MEDIA_ROOT):os.makedirs(MEDIA_ROOT)# 文件路径file_path = os.path.join(MEDIA_ROOT, new_file_name)# 将网络地址返回给小程序return_img = "http://127.0.0.1:8000/media/" + str(new_file_name)# 开始写入本地磁盘try:f = open(file_path, 'wb')# 多次写入for i in imageList.chunks():f.write(i)f.close()print("上传图片成功")# 不能用Response,result.data.status获取不到,result.data是string类型,不是object# return Response({"status": True, "message": "上传图片成功","data": file_path})# 如果返回的是JsonResponse,小程序要进行解析console.log(JSON.parse(res.data))return JsonResponse({"status": True, "message": "上传图片成功", "data": return_img})except Exception as e:print("上传图片失败:", e)return JsonResponse({"status": False, "message": "上传图片失败:" + str(e)})# 获取UUIDdef get_random_str(self):import hashlibimport uuid"""获取UUID"""uuid_val = uuid.uuid4() # UUID('c1127b61-0714-4eab-8fb0-0138b6a84b4c')uuid_str = str(uuid_val).encode('utf-8') # b'c1127b61-0714-4eab-8fb0-0138b6a84b4c'md5 = hashlib.md5() # <md5 _hashlib.HASH object @ 0x00000253D50DCDB0>md5.update(uuid_str)return md5.hexdigest() # 'fb8dfbe57e508bc4ade13f1ac4e7212b'# 退出class LogoutView(APIView):'''退出登录功能'''def post(self, request, *args, **kwargs):# 传入的tokentoken = request.data.get('token', '')phone = request.data.get('phone', '')if not token:return Response({"status": False, "message": "退出登录失败"})# 去数据库里data_token = models.UserInfo.objects.filter(token=token).first()data_token = data_token.tokenif token != data_token:return Response({"status": False, "message": "退出登录失败"})conn = get_redis_connection()# 成功退出时,清掉redis中的验证码,以便用户能登录成功后马上退出再次重新获取验证码conn.delete(phone)return Response({"status": True, "message": "已成功退出"})class PublishView(APIView):'''发布心情功能'''def post(self, request, *args, **kwargs):info = request.data.get('info','')print("***",info)return Response({"status": True, "message": "接收成功"})class LoginView(APIView):'''# 登录功能,返回status'''def post(self, request, *args, **kwargs):'''1.校验手机号2.校验验证码,redis获取验证码2.1 无验证码2.2 有验证码,但是输入错误2.3 有验证码,输入正确3.获取数据库中用户信息(创建或者获取)4.将一些信息返回给小程序'''# 传入的phonephone = request.data.get('phone', '')if not phone:return Response({"status": False, "message": "手机号不能为空"})if not phone.isdecimal():return Response({"status": False, "message": "手机号格式错误"})if len(phone) != 11:return Response({"status": False, "message": "手机号长度错误"})patt = r'^1[3-9]\d{9}$'getPhoneNum = re.match(patt, phone)if not getPhoneNum:return Response({"status": False, "message": "手机号格式错误"})phone = getPhoneNum.group()# 传入的验证码code = request.data.get('code', '')if not code:return Response({"status": False, "message": "验证码不能为空"})if len(code) != 4 or not code.isdecimal():return Response({"status": False, "message": "验证码为4位数字"})conn = get_redis_connection()# redis库里存的验证码,和用户输入的验证码进行比对,redis取值是bytes类型,因为设置了60秒过期,会有取不到的情况redis_code = conn.get(phone)if not redis_code:# 如果查不到,无效return Response({"status": False, "message": "验证码无效"})# 查看原有变量的编码类型ret = chardet.detect(redis_code)redis_code = redis_code.decode(ret['encoding'])# 如果不等输入有误if redis_code != code:return Response({"status": False, "message": "验证码输入错误"})# 获取数据库中用户信息(创建或者获取)# 第一个方法# users = models.UserInfo.objects.filter(phone=phone).first()# print("users:",users)# 如果没有用户,则创建# if not users:#models.UserInfo.objects.create(phone=phone,token=str(uuid.uuid4()))# else:#users.token = str(uuid.uuid4())#users.save()# 第二个方法flag:如果能查到返回False,查不到则创建返回Trueuser_obj, flag = models.UserInfo.objects.get_or_create(phone=phone)user_obj.token = str(uuid.uuid4())user_obj.save()if flag:return Response({"status": True, "message": "注册成功", "data": {"token": user_obj.token, "phone": phone}})return Response({"status": True, "message": "登录成功", "data": {"token": user_obj.token, "phone": phone}})# return Response({"status": True,"message": "登录成功"})class MessageView(APIView):def get(self, request, *args, **kwargs):'''接收短信验证码功能,返回四位数字fourNum'''# 1、获取手机号getPhoneNum = request.query_params.get('phone', '')# 2、手机号格式验证,否则浏览器直接输入http://127.0.0.1:8000/api/message/?phone=12000000000,也可以获取验证码# 正则判断patt = r'^1[3-9]\d{9}$'getPhoneNum = re.match(patt, getPhoneNum)if not getPhoneNum:print("手机号格式错误")return Response("手机号格式错误")phone = getPhoneNum.group()print("传递的手机号为:", phone)# 防止用户连续点击获取验证码,加了一个判断或者防止获取完验证码一分钟内退出页面再次重新进入页面,重新获取conn = get_redis_connection()redis_code = conn.get(phone)if redis_code:# 如果查到,则代表刚刚获取过不能再次获取return Response({"status": False, "message": "已获取过验证码"})# 模拟发送成功和失败,只有发送成功才生成验证码,进而存入redis# 如果发送失败,直接返回提示simulation = random.choice([True, False])if not simulation:print("验证码发送失败")return Response({"status": False, "message": "验证码发送失败"})# 3、生成四位随机验证码random_code = random.randint(1000, 9999)print("生成验证码为:", random_code)# 4、验证码发送到手机,购买服务器进行短信发送,腾讯云(可将此功能单独封装)# 4.1 注册腾讯云,开通腾讯云短信# 4.2 创建应用 SDK APPID=XXXXX# 4.3 申请签名(个人可通过公众号)获取到ID 和名称# 4.4 申请腾讯云API获得SecretID和Secretkey# 4.5 参考以下文档:Tencent Cloud SDK 3.0 for Python# /document/product/382/38778# /TencentCloud/tencentcloud-sdk-python/blob/master/examples/sms/v0711/SendSms.py# 5、保留验证码+手机号(设置超时时间过期60秒,可以用redis)# 5.1 搭建redis服务器(云redis)# 5.2 自行搭建本地# import redis# pool = redis.ConnectionPool(host='',port=6379)# r = redis.Redis(connection_pool=pool)# r.set(phone,random_code,ex=60)# 5.3 使用django-redis,首先settings中添加配置CACHES# 需要打开redisconn.set(phone, random_code, ex=60)return Response({"status": True, "message": "验证码发送成功", "fourNum": random_code})

八、在wxTest\api中添加urls.py

from django.urls import pathfrom . import viewsurlpatterns = [path('login/', views.LoginView.as_view()), # 登录path('message/', views.MessageView.as_view()), # 获取验证码path('logout/', views.LogoutView.as_view()), # 退出登录path('upload/', views.UploadView.as_view()), # 传图功能path('publish/', views.PublishView.as_view()), # 发布心情功能path('del/', views.DelView.as_view()), # 删除上传的图片]

九、运行服务

python manage.py runserver

十、打开网址login:http://127.0.0.1:8000/api/login/

打开网址message:http://127.0.0.1:8000/api/message/

打开网址:http://127.0.0.1:8000/api/logout/

打开网址:http://127.0.0.1:8000/api/upload/

如果报以下错请参考:/z564359805/article/details/115550473

OrderedDict‘ object has no attribute ‘register‘

以上设置完毕,但微信小程序wx.request的url中输入http://127.0.0.1:8000/api/login/,会报错:

http://127.0.0.1:8000 不在以下 request 合法域名列表中,请参考文档:https://developers./miniprogram/dev/framework/ability/network.html

https://developers./miniprogram/dev/framework/ability/network.html

关闭不校验合法域名功能即可:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。