• django rest framework 学习笔记-实战商城2


    01收货地址模型类和视图定义_哔哩哔哩_bilibili   本博客借鉴至大佬的视频学习笔记


    目录

    地址信息的管理:增删改查的实现

    默认收货地址的设置

    云短信使用

     验证码发送短信接口实现

     发送短信验证码限流配置

    绑定手机接口实现 - 要求: 权限认证、防止越权、验证码三分钟(通过后三分钟后清除)

    解绑手机号接口实现

    修改昵称接口的实现 - 要求: 权限校验、防止越权

    修改用户邮箱接口

     用户密码接口修改与重置接口实现


    地址信息的管理:增删改查的实现
    1. # 序列化器配置
    2. class AddrSerializer(serializers.ModelSerializer):
    3. """收货地址的模型序列化器"""
    4. class Meta:
    5. model = Addr
    6. fields = '__all__'
    7. # view 视图信息
    8. class AddrView(GenericViewSet,
    9. mixins.ListModelMixin,
    10. mixins.CreateModelMixin,
    11. mixins.DestroyModelMixin,
    12. mixins.UpdateModelMixin):
    13. """收货地址管理视图"""
    14. queryset = Addr.objects.all()
    15. serializer_class = AddrSerializer
    16. permission_classes = [IsAuthenticated,AddrPermissions]
    17. # filterset_fields = ('user',)
    18. def list(self, request, *args, **kwargs):
    19. queryset = self.filter_queryset(self.get_queryset())
    20. # 通过请求过来的用户进行过滤
    21. queryset = queryset.filter(user=request.user)
    22. page = self.paginate_queryset(queryset)
    23. if page is not None:
    24. serializer = self.get_serializer(page, many=True)
    25. return self.get_paginated_response(serializer.data)
    26. serializer = self.get_serializer(queryset, many=True)
    27. return Response(serializer.data)
    28. # url 配置
    29. # 添加地址和获取地址列表的路由
    30. path('address/', AddrView.as_view({'post':'create','get':'list'}), name='address'),
    31. # 删除和修改地址
    32. path('address//', AddrView.as_view({'delete':'destroy','put':'update'}), name='address'),
    33. # 注册过滤器
    34. 'django_filters'
    35. # 配置过滤器
    36. REST_FRAMEWORK = {
    37. # 过滤器信息配置
    38. 'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend',]
    39. }
    默认收货地址的设置
    1. # 如上 AddrView视图中增加默认地址函数
    2. def set_default_addr(self,request,*args,**kwargs):
    3. """设置默认收货地址"""
    4. # 将获取的地址设置为默认
    5. obj =self.get_object()
    6. obj.is_default =True
    7. obj.save()
    8. # 将其他地址进行遍历为非默认
    9. queryset = self.get_queryset().filter(user=request.user)
    10. for item in queryset:
    11. if item !=obj:
    12. item.is_default =False
    13. item.save()
    14. return Response({'message':'设置成功'},status=status.HTTP_200_OK)
    15. # url 文件配置
    16. path('address//default/', AddrView.as_view({'put': 'set_default_addr'}), name='address'),
    云短信使用

    网址云通信精选特惠

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

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

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

     根据上面提供的demo代码优化结果: 参考博客:Django+DRF发送短信验证码--阿里云_django对接阿里云短信-CSDN博客

    1. # -*- coding: utf-8 -*-
    2. import json
    3. from alibabacloud_dysmsapi20170525.client import Client
    4. from alibabacloud_tea_openapi.models import Config
    5. from alibabacloud_dysmsapi20170525.models import SendSmsRequest
    6. from alibabacloud_tea_util.models import RuntimeOptions
    7. class Sample:
    8. def create_client(self, access_key_id: str, access_key_secret: str):
    9. # 1. 创建一个配置对象
    10. """
    11. LTAI5tMLfxMgiu6gPycNcyTC
    12. H8LokjVLN50rDUCBqMss2juKpSownF
    13. """
    14. config = Config(
    15. # 必填,您的 AccessKey ID,
    16. access_key_id='xxx',
    17. # 必填,您的 AccessKey Secret,
    18. access_key_secret='xxx',
    19. endpoint=f'dysmsapi.aliyuncs.com'
    20. )
    21. # 2. 创建一个客服端
    22. client = Client(config)
    23. # 3. 创建短信对象
    24. send_sms_request = SendSmsRequest(
    25. sign_name='阿里云短信测试',
    26. template_code='SMS_154950909',
    27. phone_numbers='XXX',
    28. template_param='{"code":"1234"}'
    29. )
    30. # 4. 设置允许时间选项
    31. runtime = RuntimeOptions()
    32. # 5. 发送短信
    33. client.send_sms_with_options(send_sms_request, runtime)
    34. class Send_SMS():
    35. # access_key_id和 access_key_secret 为你的账号值
    36. access_key_id = 'access_key_id'
    37. access_key_secret = 'access_key_secret'
    38. endpoint = 'dysmsapi.aliyuncs.com'
    39. sign_name = '阿里云短信测试'
    40. template_code = 'SMS_154950909'
    41. def __init__(self):
    42. self.config = Config(
    43. # 必填,您的 AccessKey ID,
    44. access_key_id=self.access_key_id,
    45. # 必填,您的 AccessKey Secret,
    46. access_key_secret=self.access_key_secret,
    47. endpoint=self.endpoint
    48. )
    49. def send(self, mobile: str, code: str):
    50. """
    51. mobile: 手机号
    52. code:验证码
    53. """
    54. # 1. 创建一个客服端
    55. client = Client(self.config)
    56. send_sms_request = SendSmsRequest(
    57. phone_numbers=mobile,
    58. template_param=json.dumps({"code": code}),
    59. sign_name=self.sign_name,
    60. template_code=self.template_code,
    61. )
    62. # 2. 创建短信对象
    63. # 3. 设置允许时间选项
    64. runtime = RuntimeOptions()
    65. # 4. 发送短信
    66. client.send_sms_with_options(send_sms_request, runtime)
    67. if __name__ == '__main__':
    68. # mobile为你的手机号
    69. # code 为你想要发到手机的验证码
    70. Send_SMS().send(mobile='xxx', code='1234')
     验证码发送短信接口实现
    1. # view 视图配置
    2. class SendSmsView(APIView):
    3. """发送短信验证码"""
    4. def post(self,request):
    5. mobile = request.data.get('mobile','')
    6. pattern = '^(13\d|14[5|7]|15\d|166|17[3|6|7]|18\d)\d{8}$'
    7. if not re.match(pattern,mobile):
    8. return Response({'error': '无效的手机号码'},status=status.HTTP_422_UNPROCESSABLE_ENTITY)
    9. code = self.get_random_code()
    10. result = Send_SMS().send(mobile,code)
    11. print(result)
    12. if result['code'] == 'OK':
    13. # 短信入库
    14. obj = VerifyCode.objects.create(mobile=mobile,code=code)
    15. result['codeID']=obj.id
    16. return Response(result,status=status.HTTP_200_OK)
    17. else:
    18. return Response({'error':'发送短信失败'},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    19. def get_random_code(self):
    20. """随机生成一个六位验证码"""
    21. code = ''
    22. for i in range(6):
    23. n= random.choice(range(9))
    24. code+=str(n)
    25. return code
    26. # url 文件配置
    27. path('sendsms/', SendSmsView.as_view(), name='sms'),

    运行结果:

     发送短信验证码限流配置
    1. # view
    2. from rest_framework.throttling import UserRateThrottle,AnonRateThrottle
    3. # Create your views here.
    4. class SendSmsView(APIView):
    5. """发送短信验证码"""
    6. # 设置限流,每分钟发送短信一次
    7. throttle_classes = (AnonRateThrottle,)
    8. REST_FRAMEWORK = {
    9. 'DEFAULT_THROTTLE_RATES': {
    10. # 时间周期 second/minute/hour/day
    11. 'anon': '1/minute', # 未认证的用户 10/day sms
    12. 'user': '1/minute' # 认证的用户 100/day
    13. },
    14. }

    运行结果:

    绑定手机接口实现 - 要求: 权限认证、防止越权、验证码三分钟(通过后三分钟后清除)
    1. class UserView(GenericViewSet,mixins.RetrieveModelMixin):
    2. """用户相关的操作视图集"""
    3. queryset = User.objects.all()
    4. serializer_class = UserSerializer
    5. permission_classes = [IsAuthenticated,UserPermissions] # 设置权限认证
    6. def bind_mobile(self,request,*args,**kwargs):
    7. code =request.data.get('code') # 验证码
    8. codeID = request.data.get('codeID') # 验证码id
    9. mobile =request.data.get('mobile')
    10. if not code:
    11. return Response({'error':"验证码不可为空"},status=status.HTTP_400_BAD_REQUEST)
    12. if not codeID:
    13. return Response({'error':"验证码ID不可为空"},status=status.HTTP_400_BAD_REQUEST)
    14. if not mobile:
    15. return Response({'error':"手机号不可为空"},status=status.HTTP_400_BAD_REQUEST)
    16. if VerifyCode.objects.filter(id=codeID,code=code,mobile=mobile).exists():
    17. # 检验验证码是否过期,过期时间3分钟
    18. c_obj = VerifyCode.objects.get(id=codeID,code=code,mobile=mobile)
    19. # 获取验证码的创建的时间
    20. ct = c_obj.create_time.timestamp()
    21. # 当前时间的时间戳
    22. et = time.time()
    23. # 删除验证码,避免同一个验证码重复请求
    24. c_obj.delete()
    25. if ct + 180 < et:
    26. return Response({'error': "验证码已过期"}, status=status.HTTP_400_BAD_REQUEST)
    27. # else:
    28. # return Response({'error': "无效的验证码,请重新获取验证码"}, status=status.HTTP_400_BAD_REQUEST)
    29. if User.objects.filter(mobile=mobile).exists():
    30. return Response({'error':"该手机号已被其他用户绑定"},status=status.HTTP_400_BAD_REQUEST)
    31. # 绑定手机号
    32. user = request.user
    33. user.mobile = mobile
    34. user.save()
    35. return Response({'error':"绑定成功"},status=status.HTTP_200_OK)
    36. # 绑定手机号
    37. path('/mobile/bind/', UserView.as_view({'put': 'bind_mobile'}), name='avatar_post'),
    解绑手机号接口实现
    1. @staticmethod
    2. def verify_code(code,codeID,mobile):
    3. if not code:
    4. return {'error': "验证码不可为空"}
    5. if not codeID:
    6. return {'error': "验证码ID不可为空"}
    7. if not mobile:
    8. return {'error': "手机号不可为空"}
    9. if VerifyCode.objects.filter(id=codeID, code=code, mobile=mobile).exists():
    10. # 检验验证码是否过期,过期时间3分钟
    11. c_obj = VerifyCode.objects.get(id=codeID, code=code, mobile=mobile)
    12. # 获取验证码的创建的时间
    13. ct = c_obj.create_time.timestamp()
    14. # 当前时间的时间戳
    15. et = time.time()
    16. # 删除验证码,避免同一个验证码重复请求
    17. c_obj.delete()
    18. if ct + 180 < et:
    19. return {'error': "验证码已过期"}
    20. else:
    21. return {'error': "无效的验证码,请重新获取验证码"}
    22. def ubind_mobile(self,request,*args,**kwargs):
    23. code = request.data.get('code') # 验证码
    24. codeID = request.data.get('codeID') # 验证码id
    25. mobile = request.data.get('mobile')
    26. result = self.verify_code(code,codeID,mobile)
    27. if result:
    28. return Response(result,status=status.HTTP_400_BAD_REQUEST)
    29. # 解绑手机号,验证用户已绑定手机号
    30. user = request.user
    31. if user.mobile ==mobile:
    32. user.mobile = ''
    33. user.save()
    34. return Response({'error': "解帮成功"}, status=status.HTTP_200_OK)
    35. else:
    36. return Response({"error":"当前用户未绑定该号码"},status=status.HTTP_400_BAD_REQUEST)
    37. # url
    38. # 解绑手机号
    39. path('/mobile/ubind/', UserView.as_view({'put': 'ubind_mobile'}), name='ubind_mobile'), # 检验token
    修改昵称接口的实现 - 要求: 权限校验、防止越权
    1. class UserView(GenericViewSet,mixins.RetrieveModelMixin):
    2. """用户相关的操作视图集"""
    3. queryset = User.objects.all()
    4. serializer_class = UserSerializer
    5. permission_classes = [IsAuthenticated,UserPermissions] # 设置权限认证
    6. def update_name(self,request,*args,**kwargs):
    7. last_name = request.data.get('last_name')
    8. if not last_name:
    9. return Response({'error':"参数last_name 不可为空"},status=status.HTTP_400_BAD_REQUEST)
    10. user = self.get_object()
    11. user.last_name = last_name
    12. user.save()
    13. return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
    14. # url
    15. # 修改用户昵称
    16. path('/name/', UserView.as_view({'put': 'update_name'}), name='update_name'), # 检验token
    修改用户邮箱接口
    1. # view
    2. def update_email(self,request,*args,**kwargs):
    3. email = request.data.get('email')
    4. if not email:
    5. return Response({'error':"邮箱参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
    6. pattern = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
    7. if not re.match(pattern,email):
    8. return Response({'error':"邮箱格式错误"},status=status.HTTP_400_BAD_REQUEST)
    9. user = self.get_object()
    10. # 检验是否新旧一致
    11. if user.email ==email:
    12. return Response({'error':"不能和旧邮箱保持一致"},status=status.HTTP_200_OK)
    13. if User.objects.filter(email=email).exists():
    14. return Response({'error':"邮箱已被其他用户绑定"},status=status.HTTP_400_BAD_REQUEST)
    15. user.email = email
    16. user.save()
    17. return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
    18. # url
    19. # 修改用户邮箱
    20. path('/email/', UserView.as_view({'put': 'update_email'}), name='update_email'),
     用户密码接口修改与重置接口实现

    要求:权限认证、防止越权、检验验证码、验证过期3分钟检验并通过后删除

    1. # view
    2. def update_password(self,request,*args,**kwargs):
    3. password = request.data.get('password')
    4. password_confirmation = request.data.get('password_confirmation')
    5. code = request.data.get('code') # 验证码
    6. codeID = request.data.get('codeID') # 验证码id
    7. mobile = request.data.get('mobile')
    8. result = self.verify_code(code,codeID,mobile)
    9. if result:
    10. return Response(result,status=status.HTTP_400_BAD_REQUEST)
    11. email = request.data.get('email')
    12. if not email:
    13. return Response({'error':"邮箱参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
    14. user = self.get_object()
    15. # 检验是否新旧一致
    16. if user.mobile !=mobile:
    17. return Response({'error':"验证码有误"},status=status.HTTP_400_BAD_REQUEST)
    18. if not password:
    19. return Response({'error':"密码参数不可为空"},status=status.HTTP_400_BAD_REQUEST)
    20. if password !=password_confirmation:
    21. return Response({'error':"两次输入的密码不一致"},status=status.HTTP_400_BAD_REQUEST)
    22. # 修改用户密码 set_password 密码在数据中是加密的
    23. user.set_password(password)
    24. user.save()
    25. return Response({'message': "修改成功"}, status=status.HTTP_200_OK)
    26. # url
    27. # 修改用户密码
    28. path('/password/', UserView.as_view({'put': 'update_password'}), name='update_password'),

     

  • 相关阅读:
    vm虚拟机克隆ubuntu
    河南省文化旅游发展相关统计数据(2014-2023年)
    现在都这么狂吗?今天面试了一个工作4年的测试工程师,一问连自动化基础都不知道,还反过来怼我..
    检验检疫系统(LIS)源码:C# + MVC + SQLserver + Redis
    基于.NET Core + Quartz.NET+ Vue + IView开箱即用的定时任务UI
    弹性构建:Kylin Cube构建失败的智能重试机制
    案例分享 | 数字化综合人才管理平台
    微信公众号订阅消息
    【Spring】Bean 的作用域和生命周期
    BUUCTF中的web
  • 原文地址:https://blog.csdn.net/qq_44238024/article/details/136222785