rest_framework校验前端传递过来的字段--Serializer

drf–验证前端传递过来的数据

  • 前端传来的数据先走mixins,然后进行验证,验证通过后,就会调用ModelSerializer的create或者update方法,如果继承的是Serializer,就需要自己重载Serializer中的create或者update方法,或者修改mixins的create等方法的逻辑进行保存。

  • serializer和form一样, 验证都是在serializer和form里验证

  • views–重写了CreateModelMixin下的create方法

    from rest_framework.mixins import CreateModelMixin
    from rest_framework import viewsets
    # 返回的响应体
    from rest_framework.response import Response
    # 状态码
    from rest_framework import status
    
    from .models import VerifyCode
    from .serializers import SmsSerializer
    from MxShop.settings import API_KEY
    from utils.yunpian import YunPian
    
    
    class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet):
        """
        发送短信验证码
        """
    
        # 指定序列化类
        serializer_class = SmsSerializer
    
        # 生成验证码
        def generate_code(self):
            """
            生成4位的验证码
            :return: 验证码
            """
            seeds = "1234567890"
            code = ""
            for i in range(4):
                code += random.choice(seeds)
            return code
    
        # 重写创建方法
        def create(self, request, *args, **kwargs):
            # 这个serializer就是我们指定的serializer
            serializer = self.get_serializer(data=request.data)
            # raise_exception=True 表示验证失败 直接抛异常  不会往下走了
            serializer.is_valid(raise_exception=True)
    		# 上面那两行代码必须
    		 
            # 取出手机号码
            # validated_data保存着前端传递过来的数据
            mobile = serializer.validated_data["mobile"]
    
            # 获取验证码
            code = self.generate_code()
    
            # 接入云片网发送短信
            # 创建对象, 传入APIKEY 这个APIKEY是你云片网账号里面的APIKEY 我把它设置在settings里面了
            yunpian = YunPian(API_KEY)
            sms_status = yunpian.send_sms(code=code, mobile=mobile)
    
            # 返回结果code为0表示发送成功
            if sms_status["code"] != 0:
                # 返回失败原型
                return Response({
                    # 手机号
                    "mobile": sms_status["mobile"]
                    # 状态码
                }, status=status.HTTP_400_BAD_REQUEST)
    
            code_record = VerifyCode(code=code, mobile=mobile)
            code_record.save()
    
            # 发送成功
            return Response({
                "mobile": sms_status["mobile"]
            }, status=status.HTTP_201_CREATED)
    
  • create的源码
    rest_framework校验前端传递过来的字段--Serializer_第1张图片

  • serializer–这里不用ModelSerializer是因为发送验证码时只需要提交一个手机号码过来, 而验证码表里面code又是必填字段, 所以说我们用ModelSerializer来做验证的话就会有一个问题, 你提交手机号码过来, code又是必填字段, 所以code会验证失败, 所以这里用Serializer自己写逻辑

    import re
    from datetime import datetime
    from datetime import timedelta
    
    from rest_framework import serializers
    
    from django.contrib.auth import get_user_model
    # 正则表达式放在settings中
    from MxShop.settings import REGEX_MOBILE
    
    from .models import VerifyCode
    
    # 获取用户模型类
    UserProfile = get_user_model()
    
    
    class SmsSerializer(serializers.Serializer):
      	# 获取序列化的字段
        mobile = serializers.CharField(max_length=11)
    
        # 验证序列化的字段
        # 验证的方法名必须是 validate_ + 要验证的字段名
        def validate_mobile(self, mobile):
            """
            验证手机号码
            :param mobile:手机号码
            :return:
            """
            # 校验手机号是否合法
            if not re.match(REGEX_MOBILE, mobile):
              	# 抛出异常
                raise serializers.ValidationError("手机号码不合法")
    
            # 校验手机号是否被注册
            if UserProfile.objects.filter(mobile=mobile):
                raise serializers.ValidationError("该手机号码已注册")
    
            # 验证发送频率
            # 获取一分钟前的时间
            one_mintes_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
    
            # 已经存在数据库添加时间 > 一分钟前的时间 并且 手机号也是该手机号
            if VerifyCode.objects.filter(add_time__gt=one_mintes_ago, mobile=mobile):
                raise serializers.ValidationError("请60秒后重试, 谢谢")
    
            return mobile
    
  • url

    from rest_framework.routers import DefaultRouter
    
    from users.views import SmsCodeViewSet
    
    # 生成一个注册器实例对象
    router = DefaultRouter()
    
    # 配置发送验证码url
    router.register(r'codes', SmsCodeViewSet, base_name="codes")
    
    urlpatterns = [
        # 自动生成url
        url(r"^", include(router.urls)),
    ]
    

你可能感兴趣的:(drf-验证,rest_framework)