01收货地址模型类和视图定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记
目录
绑定手机接口实现 - 要求: 权限认证、防止越权、验证码三分钟(通过后三分钟后清除)
- # 序列化器配置
- class AddrSerializer(serializers.ModelSerializer):
- """收货地址的模型序列化器"""
- class Meta:
- model = Addr
- fields = '__all__'
-
-
-
- # view 视图信息
- class AddrView(GenericViewSet,
- mixins.ListModelMixin,
- mixins.CreateModelMixin,
- mixins.DestroyModelMixin,
- mixins.UpdateModelMixin):
- """收货地址管理视图"""
- queryset = Addr.objects.all()
- serializer_class = AddrSerializer
- permission_classes = [IsAuthenticated,AddrPermissions]
- # filterset_fields = ('user',)
-
- def list(self, request, *args, **kwargs):
- queryset = self.filter_queryset(self.get_queryset())
- # 通过请求过来的用户进行过滤
- queryset = queryset.filter(user=request.user)
- page = self.paginate_queryset(queryset)
- if page is not None:
- serializer = self.get_serializer(page, many=True)
- return self.get_paginated_response(serializer.data)
-
- serializer = self.get_serializer(queryset, many=True)
- return Response(serializer.data)
-
-
- # url 配置
- # 添加地址和获取地址列表的路由
- path('address/', AddrView.as_view({'post':'create','get':'list'}), name='address'),
- # 删除和修改地址
- path('address/
/' , AddrView.as_view({'delete':'destroy','put':'update'}), name='address'), -
- # 注册过滤器
- 'django_filters'
-
- # 配置过滤器
- REST_FRAMEWORK = {
- # 过滤器信息配置
- 'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend',]
- }
-
- # 如上 AddrView视图中增加默认地址函数
- def set_default_addr(self,request,*args,**kwargs):
- """设置默认收货地址"""
- # 将获取的地址设置为默认
- obj =self.get_object()
- obj.is_default =True
- obj.save()
- # 将其他地址进行遍历为非默认
- queryset = self.get_queryset().filter(user=request.user)
- for item in queryset:
- if item !=obj:
- item.is_default =False
- item.save()
- return Response({'message':'设置成功'},status=status.HTTP_200_OK)
-
- # url 文件配置
- path('address/
/default/' , AddrView.as_view({'put': 'set_default_addr'}), name='address'),
网址云通信精选特惠

购买成功后进入控制台,搜索短信服务:阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台



点击当前的SDK信息,安装依赖

找到控制台的快捷操作,创建access_key_id 和access_key_secret

根据上面提供的demo代码优化结果: 参考博客:Django+DRF发送短信验证码--阿里云_django对接阿里云短信-CSDN博客
- # -*- coding: utf-8 -*-
- import json
- from alibabacloud_dysmsapi20170525.client import Client
- from alibabacloud_tea_openapi.models import Config
- from alibabacloud_dysmsapi20170525.models import SendSmsRequest
- from alibabacloud_tea_util.models import RuntimeOptions
-
-
- class Sample:
- def create_client(self, access_key_id: str, access_key_secret: str):
- # 1. 创建一个配置对象
- """
- LTAI5tMLfxMgiu6gPycNcyTC
- H8LokjVLN50rDUCBqMss2juKpSownF
- """
- config = Config(
- # 必填,您的 AccessKey ID,
- access_key_id='xxx',
- # 必填,您的 AccessKey Secret,
- access_key_secret='xxx',
- endpoint=f'dysmsapi.aliyuncs.com'
-
- )
- # 2. 创建一个客服端
- client = Client(config)
- # 3. 创建短信对象
- send_sms_request = SendSmsRequest(
- sign_name='阿里云短信测试',
- template_code='SMS_154950909',
- phone_numbers='XXX',
- template_param='{"code":"1234"}'
- )
- # 4. 设置允许时间选项
- runtime = RuntimeOptions()
- # 5. 发送短信
- client.send_sms_with_options(send_sms_request, runtime)
-
- class Send_SMS():
- # access_key_id和 access_key_secret 为你的账号值
- access_key_id = 'access_key_id'
- access_key_secret = 'access_key_secret'
- endpoint = 'dysmsapi.aliyuncs.com'
- sign_name = '阿里云短信测试'
- template_code = 'SMS_154950909'
-
- def __init__(self):
- self.config = Config(
- # 必填,您的 AccessKey ID,
- access_key_id=self.access_key_id,
- # 必填,您的 AccessKey Secret,
- access_key_secret=self.access_key_secret,
- endpoint=self.endpoint
- )
-
- def send(self, mobile: str, code: str):
- """
- mobile: 手机号
- code:验证码
- """
- # 1. 创建一个客服端
- client = Client(self.config)
- send_sms_request = SendSmsRequest(
- phone_numbers=mobile,
- template_param=json.dumps({"code": code}),
- sign_name=self.sign_name,
- template_code=self.template_code,
-
- )
- # 2. 创建短信对象
- # 3. 设置允许时间选项
- runtime = RuntimeOptions()
- # 4. 发送短信
- client.send_sms_with_options(send_sms_request, runtime)
-
-
- if __name__ == '__main__':
- # mobile为你的手机号
- # code 为你想要发到手机的验证码
- Send_SMS().send(mobile='xxx', code='1234')
- # view 视图配置
- class SendSmsView(APIView):
- """发送短信验证码"""
- def post(self,request):
- mobile = request.data.get('mobile','')
- pattern = '^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$'
- if not re.match(pattern,mobile):
- return Response({'error': '无效的手机号码'},status=status.HTTP_422_UNPROCESSABLE_ENTITY)
- code = self.get_random_code()
- result = Send_SMS().send(mobile,code)
- print(result)
- if result['code'] == 'OK':
- # 短信入库
- obj = VerifyCode.objects.create(mobile=mobile,code=code)
- result['codeID']=obj.id
- return Response(result,status=status.HTTP_200_OK)
- else:
- return Response({'error':'发送短信失败'},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
- def get_random_code(self):
- """随机生成一个六位验证码"""
- code = ''
- for i in range(6):
- n= random.choice(range(9))
- code+=str(n)
- return code
-
- # url 文件配置
- path('sendsms/', SendSmsView.as_view(), name='sms'),
运行结果:

- # view
- from rest_framework.throttling import UserRateThrottle,AnonRateThrottle
- # Create your views here.
- class SendSmsView(APIView):
- """发送短信验证码"""
- # 设置限流,每分钟发送短信一次
- throttle_classes = (AnonRateThrottle,)
-
- REST_FRAMEWORK = {
- 'DEFAULT_THROTTLE_RATES': {
- # 时间周期 second/minute/hour/day
- 'anon': '1/minute', # 未认证的用户 10/day sms
- 'user': '1/minute' # 认证的用户 100/day
- },
- }
运行结果:

- class UserView(GenericViewSet,mixins.RetrieveModelMixin):
- """用户相关的操作视图集"""
- queryset = User.objects.all()
- serializer_class = UserSerializer
- permission_classes = [IsAuthenticated,UserPermissions] # 设置权限认证
-
-
- def bind_mobile(self,request,*args,**kwargs):
- code =request.data.get('code') # 验证码
- codeID = request.data.get('codeID') # 验证码id
- mobile =request.data.get('mobile')
- if not code:
- return Response({'error':"验证码不可为空"},status=status.HTTP_400_BAD_REQUEST)
- if not codeID:
- return Response({'error':"验证码ID不可为空"},status=status.HTTP_400_BAD_REQUEST)
- if not mobile:
- return Response({'error':"手机号不可为空"},status=status.HTTP_400_BAD_REQUEST)
- if VerifyCode.objects.filter(id=codeID,code=code,mobile=mobile).exists():
- # 检验验证码是否过期,过期时间3分钟
- c_obj = VerifyCode.objects.get(id=codeID,code=code,mobile=mobile)
- # 获取验证码的创建的时间
- ct = c_obj.create_time.timestamp()
- # 当前时间的时间戳
- et = time.time()
- # 删除验证码,避免同一个验证码重复请求
- c_obj.delete()
- if ct + 180 < et:
- return Response({'error': "验证码已过期"}, status=status.HTTP_400_BAD_REQUEST)
- # else:
- # return Response({'error': "无效的验证码,请重新获取验证码"}, status=status.HTTP_400_BAD_REQUEST)
-
- if User.objects.filter(mobile=mobile).exists():
- return Response({'error':"该手机号已被其他用户绑定"},status=status.HTTP_400_BAD_REQUEST)
- # 绑定手机号
- user = request.user
- user.mobile = mobile
- user.save()
- return Response({'error':"绑定成功"},status=status.HTTP_200_OK)
-
- # 绑定手机号
- path('
/mobile/bind/' , UserView.as_view({'put': 'bind_mobile'}), name='avatar_post'),
- @staticmethod
- def verify_code(code,codeID,mobile):
- if not code:
- return {'error': "验证码不可为空"}
- if not codeID:
- return {'error': "验证码ID不可为空"}
- if not mobile:
- return {'error': "手机号不可为空"}
- if VerifyCode.objects.filter(id=codeID, code=code, mobile=mobile).exists():
- # 检验验证码是否过期,过期时间3分钟
- c_obj = VerifyCode.objects.get(id=codeID, code=code, mobile=mobile)
- # 获取验证码的创建的时间
- ct = c_obj.create_time.timestamp()
- # 当前时间的时间戳
- et = time.time()
- # 删除验证码,避免同一个验证码重复请求
- c_obj.delete()
- if ct + 180 < et:
- return {'error': "验证码已过期"}
- else:
- return {'error': "无效的验证码,请重新获取验证码"}
- def ubind_mobile(self,request,*args,**kwargs):
- code = request.data.get('code') # 验证码
- codeID = request.data.get('codeID') # 验证码id
- mobile = request.data.get('mobile')
- result = self.verify_code(code,codeID,mobile)
- if result:
- return Response(result,status=status.HTTP_400_BAD_REQUEST)
- # 解绑手机号,验证用户已绑定手机号
- user = request.user
- if user.mobile ==mobile:
- user.mobile = ''
- user.save()
- return Response({'error': "解帮成功"}, status=status.HTTP_200_OK)
-
- else:
- return Response({"error":"当前用户未绑定该号码"},status=status.HTTP_400_BAD_REQUEST)
-
- # url
- # 解绑手机号
- path('
/mobile/ubind/' , UserView.as_view({'put': 'ubind_mobile'}), name='ubind_mobile'), # 检验token
- class UserView(GenericViewSet,mixins.RetrieveModelMixin):
- """用户相关的操作视图集"""
- queryset = User.objects.all()
- serializer_class = UserSerializer
- permission_classes = [IsAuthenticated,UserPermissions] # 设置权限认证
-
- def update_name(self,request,*args,**kwargs):
- last_name = request.data.get('last_name')
- if not last_name:
- return Response({'error':"参数last_name 不可为空"},status=status.HTTP_400_BAD_REQUEST)
- user = self.get_object()
- user.last_name = last_name
- user.save()
- return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
-
- # url
- # 修改用户昵称
- path('
/name/' , UserView.as_view({'put': 'update_name'}), name='update_name'), # 检验token
- # view
- def update_email(self,request,*args,**kwargs):
- email = request.data.get('email')
- if not email:
- return Response({'error':"邮箱参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
- pattern = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
- if not re.match(pattern,email):
- return Response({'error':"邮箱格式错误"},status=status.HTTP_400_BAD_REQUEST)
- user = self.get_object()
- # 检验是否新旧一致
- if user.email ==email:
- return Response({'error':"不能和旧邮箱保持一致"},status=status.HTTP_200_OK)
- if User.objects.filter(email=email).exists():
- return Response({'error':"邮箱已被其他用户绑定"},status=status.HTTP_400_BAD_REQUEST)
- user.email = email
- user.save()
- return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
-
-
- # url
- # 修改用户邮箱
- path('
/email/' , UserView.as_view({'put': 'update_email'}), name='update_email'),
要求:权限认证、防止越权、检验验证码、验证过期3分钟检验并通过后删除
- # view
- def update_password(self,request,*args,**kwargs):
- password = request.data.get('password')
- password_confirmation = request.data.get('password_confirmation')
- code = request.data.get('code') # 验证码
- codeID = request.data.get('codeID') # 验证码id
- mobile = request.data.get('mobile')
- result = self.verify_code(code,codeID,mobile)
- if result:
- return Response(result,status=status.HTTP_400_BAD_REQUEST)
- email = request.data.get('email')
- if not email:
- return Response({'error':"邮箱参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
- user = self.get_object()
- # 检验是否新旧一致
- if user.mobile !=mobile:
- return Response({'error':"验证码有误"},status=status.HTTP_400_BAD_REQUEST)
- if not password:
- return Response({'error':"密码参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
- if password !=password_confirmation:
- return Response({'error':"两次输入的密码不一致"},status=status.HTTP_400_BAD_REQUEST)
-
- # 修改用户密码 set_password 密码在数据中是加密的
- user.set_password(password)
- user.save()
- return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
-
- # url
- # 修改用户密码
- path('
/password/' , UserView.as_view({'put': 'update_password'}), name='update_password'),

