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

news2024/9/22 17:31:18

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/<int:pk>/', 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/<int:pk>/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('<int:pk>/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('<int:pk>/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('<int:pk>/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('<int:pk>/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('<int:pk>/password/', UserView.as_view({'put': 'update_password'}), name='update_password'),

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1464293.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

ELK入门(四)-logstash

Logstash Logstash 是开源的服务器端数据处理管道&#xff0c;能够同时从多个来源采集数据&#xff0c;转换数据&#xff0c;然后将数据发送到您最喜欢的存储库中。 Logstash 能够动态地采集、转换和传输数据&#xff0c;不受格式或复杂度的影响。利用 Grok 从非结构化数据中…

Kotlin基础 7

1.apply函数详解 1.1. DSL /*** 为什么要传入扩展函数(泛型),而不是一个普通的匿名函数* T.()->Unit* 扩展函数里自带了接收者对象的this隐式调用* 为什么是泛型的扩展函数?* 因为是由this 隐式调用 this 类型就是泛型类型&#xff0c; 相当于this的扩展函数&#xff0c;…

短剧小程序开发,重塑视频观看体验的科技革命

随着科技的飞速发展&#xff0c;人们的娱乐方式也在不断变化。短剧小程序作为新兴的数字娱乐形式&#xff0c;以其独特的魅力和巨大的市场潜力&#xff0c;正逐渐成为科技与娱乐结合的代表。本文将探讨短剧小程序的发展背景、优势特点、开发流程以及未来展望。 一、短剧小程序…

MySQL数据库集群技术主从复制 一主一从详细讲解

集群技术 集群概述 MySQL复制技术 集群目的 负载均衡 解决高并发 高可用HA 服务可用性 远程灾备 数据有效性 类型 一主一从 一主双从 双主双从 原理 概念 在主库上把数据更改&#xff08;DDL DML DCL&#xff09;记录到二进制日志&#xff08;Binary Log&#xff09;中…

RISC-V知识总结 —— 指令集

资源1: RISC-V China – RISC-V International 资源2: RISC-V International – RISC-V: The Open Standard RISC Instruction Set Architecture 资源3: RV32I, RV64I Instructions — riscv-isa-pages documentation 1. 指令集架构的类型 在讨论RISC-V或任何处理器架构时&…

Code Release Process

Code Control Process-CSDN博客 代码发布流程&#xff08;Code Release Process&#xff09;

Java毕业设计-基于ssm的校园二手交易管理系统-第67期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于ssm的校园二手交易管理系统&#xff1a;前端jsp、jquery&#xff0c;后端 springmvc、spring、mybatis&#xff0c;集成商品管理、订单管理、销售管理、采购管理、购…

vue.js el-tooltip根据文字长度控制是否提示toolTip

一、需求&#xff1a;如何判断当前文本文字是否超出文本长度&#xff0c;是否需要出现提示toolTip。效果图如下&#xff1a; 二、实现&#xff1a; 1、表格字段鼠标放置el-popover出现 “引用主题” 的具体内容&#xff1b; <!-- 表格字段&#xff1a;引用主题 --> <…

Azuki NFT 概览与数据分析

作者&#xff1a;stellafootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;Azuki NFT Collection Dashboard Azuki NFT 将动漫艺术与实用性相结合&#xff0c;培育了一个充满活力的 Web3 社区。 这个 NFT 项目会在 2024 年崛起吗&#xff1f; …

数字化转型导师坚鹏:政府数字化转型之数字建设、发展与创新

政府数字化转型之数字基础设施建设、发展与创新 课程背景&#xff1a; 数字化背景下&#xff0c;很多政府存在以下问题&#xff1a; 不清楚数字基础设施建设现状&#xff1f; 不清楚数字基础设施发展趋势&#xff1f; 不清楚数字基础设施创新案例&#xff1f; 课程特色…

《优化接口设计的思路》系列:第八篇—分页接口的设计和优化

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 第六篇—接口防抖(防重复提交)的一些方式 第七篇—接口限流策略 第八篇—分页接口的设计和优化 …

LeetCode刷题计划----day5

19 力扣链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/description/ 文章讲解链接&#xff1a;https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8…

奇怪的需求之与图片做交互

1.起因 客户想要展示自己的地图,该地图上有各种工作数据,和工作点位,已有的地图不能满足需求.于是提出将这张图片当成大背景 2.经过 鉴于文件格式和尺寸的原因,协商后客户提出将图片做成缩放效果,同时具有点击效果,原先直接进入的主页,现在为点击图片中的某条线路进入主页面…

WordPres Bricks Builder 前台RCE漏洞复现(CVE-2024-25600)

0x01 产品简介 Bricks Builder是一款用于WordPress的开发主题,提供直观的拖放界面,用于设计和构建WordPress网站。它使用户能够轻松创建自定义的网页布局和设计,无需编写或了解复杂的代码。Bricks Builder具有用户友好的界面和强大的功能,使用户可以通过简单的拖放操作添加…

【力扣hot100】刷题笔记Day9

前言 阴天睡得还挺舒服&#xff0c;9点半才醒&#xff0c;用刷题开启美好新一天&#xff01; 141. 环形链表 - 力扣&#xff08;LeetCode&#xff09; 哈希表 class Solution:def hasCycle(self, head: Optional[ListNode]) -> bool:seen set() # 哈希集合# seen {} #…

Web前端3D JS框架和库 整理

在WebGL库和SVG/Canvas元素的支持下&#xff0c;JavaScript变得惊人的强大。几乎可以为网络构建任何东西&#xff0c;包括基于浏览器的游戏和本地应用&#xff0c;许多最新的突破性功能都在3D上运行。 为此&#xff0c;「数维图小编」整理了19个交互式3D Javascript库和框架&am…

龙年加密行业能否迎来发展春天?行业大咖带你探秘投资风口

在过去数年里&#xff0c;加密行业的牛熊市转换&#xff0c;时刻牵动着行业人士的心。无论是初入加密行业的开发新人&#xff0c;还是金融行业经验拉满的投资大佬&#xff0c;都在变动不居的环境下探寻着适应行业发展、捕捉创新机遇的方向。这一过程中&#xff0c;如何专注项目…

(十四)【Jmeter】线程(Threads(Users))之开放模型线程组(Open Model Thread Group)

简述 操作路径如下: 开放模型线程组(Open Model Thread Group) 是 JMeter 5.5 版本中引入的一个新特性,它允许用户创建具有可变负载的负载配置文件。相较于传统的线程组,开放模型线程组提供了更多的灵活性和动态调整的能力。 优点: 灵活性:允许测试人员根据测试需求动…

【EI会议征稿通知】第五届管理科学与工程管理国际学术会议(ICMSEM 2024)

第五届管理科学与工程管理国际学术会议&#xff08;ICMSEM 2024&#xff09; 2024 5th International Conference on Management Science and Engineering Management 第五届管理科学与工程管理国际学术会议 (ICMSEM 2024&#xff09;将于2024年6月07-09日于中国沈阳召开。会…