关于python的DRF框架中的数据校验方式

在使用DRF编写接口时,使用序列化器进行反序列化,校验数据大致分3步

  1. 在获取反序列化的数据前,必须调用is_valid() 方法进行验证,验证成功返回True,否则返回False。
  2. 验证失败,可以通过序列化器对象的errors 属性获取错误信息,返回字典,包含了字段和字段的错误。如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
  3. 验证成功,可以通过序列化器对象的validated_data属性获取数据。

一、继承Serializer

继承Serializer(序列化器基类,drf中所有的序列化器类都必须继承于 Serializer),直接写在参数 里和写在函数

1.校验规则直接写在参数中

python 复制代码
from rest_framework import serializers

class demoSerializer(serializers.Serializer):
    amount = serializers.IntegerField(max_value=100, min_value=0, error_messages={
        "min_value": "The Age Filed Must Be 0 <= amount",  # amount在反序列化必须是 0 <= amount <= 100
        "max_value": "The amount Filed Must Be amount <= 100",
    })

返回给前端:

python 复制代码
class DemoAPIView(APIView):
     def post(self, request, *args):
       try:
          serializer = demoSerializer(data=request.data)
          serializer.is_valid(raise_exception=True)
          # 拿出已验证的数据中的data
          validated_data = ser.validated_data.get('amount')
          #  返回信息
          return Response({"msg": "ok", "data":validated_data}, status=status.HTTP_201_CREATED)
       except ValidationError as e:
           return Response({"msg": "error", "error_message": e.detail}, status=status.HTTP_401_UNAUTHORIZED)

在DRF的序列化器中,raise_exception是一个可选参数,用于控制是否在验证失败时引发ValidationError异常。它的默认值是False,即当验证失败时,不会引发异常,而是将错误消息存储在序列化器的errors属性中。 这里的e.detail指的就是demoSerializer中amount的error_message。

2、写在函数里

继承Serializer,写在定义的validate函数中,一种是外部函数,一种是内部,其中写在内部的又分为两种,一种是校验多个字段,一种是校验单个字段

a.外部函数

写一个校验函数,在demoSerializer以外,可以导入的形式

python 复制代码
from rest_framework import serializers

def check_num(data):
        """外部验证函数"""
         if len(data) != 3:
         raise serializers.ValidationError(detail="num格式不正        确!必须是3个字符", code="check_num")
       # 验证完成以后,务必返回结果,否则最终的验证结果没有该数据
         return data
      
class demoSerializer(serializers.Serializer):
   num = serializers.CharField(validators=[check_classmate])
     

返回给前端方式和上面一样

b.写在内部函数里

内部又分为两个,写在demoSerializer里面,一种适合验证多个的validate函数,一种是验证单个的validate_name函数

验证多个字段

python 复制代码
class demoSerializer(serializers.Serializer):
   name = serializers.CharField(required=True)   # required=True , 反序列化阶段必填
    sex = serializers.BooleanField(default=True)  # default=True,  反序列化阶段,客户端没有提交,则默认为True
   
   def validate(self, attrs):
        """
        验证来自客户端的所有数据
        类似会员注册的密码和确认密码,就只能在validate方法中校验
        validate是固定方法名,
        参数:attrs,是在序列化器实例化时的data选项数据
        """
        if attrs.get("name") == "xxx" and attrs.get("sex"):
            raise serializers.ValidationError(detail="错误信息xx", code="validate")

        return attrs

    def validate_name(self, data):
        """验证单个字段
        方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
        validate开头的方法,会自动被is_valid调用的
        """
        if data in ["python", "django"]:
            # 在序列化器中,验证失败可以通过抛出异常的方式来告知 is_valid
            raise serializers.ValidationError(detail="错误信息", code="validate_name")
        # 验证成功以后,必须返回数据,否则最终的验证结果中,就不会出现这个数据了。
        return data  

返回前端方式如上

验证单个字段

python 复制代码
class demoSerializer(serializers.Serializer):
  name = serializers.CharField(required=True,
validators=[validate_name])   # required=True , 反序列化阶段必填
   def validate_name(self, data):
       """验证单个字段
       方法名的格式必须以 validate_<字段名> 为名称,否则序列化器不识别!
       validate开头的方法,会自动被is_valid调用的
       """
       if data in ["python", "django"]:
           # 在序列化器中,验证失败可以通过抛出异常的方式来告知 is_valid
           raise serializers.ValidationError(detail="错误信息", code="validate_name")
       # 验证成功以后,必须返回数据,否则最终的验证结果中,就不会出现这个数据了。
       return data  

二、继承的是ModelSerializer

models.py

py 复制代码
from django.db import models
# Create your models here.
class DemoModel(models.Model):
    """信息"""
    price = models.IntegerField(verbose_name="价格")
    class Meta:
        db_table = "mysql_demo"
        verbose_name = "demotest"
        verbose_name_plural = verbose_name

此时serializers.py应该是:

python 复制代码
from rest_framework import serializers
from .models import DemoModel  #一定要导入models,py里写的model

class DemoModelSerializer(serializers.ModelSerializer):
    #...... 其他代码
    class Meta:
        model = DemoModel
        fields = "__all__"
        extra_kwargs = {
            "age": {
                "max_value": 100,
                "error_messages": {
                    "max_value": "价格不能超过100!",
                }
            }
        }

fields = ["字段1","字段2",....] 我这里的all指的是所有的字段。 views.py返回给前端的代码和上面相同

over

相关推荐
数据智能老司机5 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机6 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i6 小时前
drf初步梳理
python·django
每日AI新事件6 小时前
python的异步函数
python
这里有鱼汤7 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook16 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室17 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三18 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试