DRF 序列化器(Serializer)

本篇重点介绍 DRF 序列化器基础使用方法,并带有一个演示案例

介绍

概念

  • 序列化 序列化器会将模型类对象转化为字典,response 后变成 json 字符串。

  • 反序列化 把客户发送过来的数据, request 后变成字典,序列化器可以将字典转成模型,同时校验客户发送数据的合法性。

  • 序列化器(类) 开发者定义的一个实现序列化和反序列化的类。

  • 模型序列化器(类) 一种对应 Django 模型的序列化器。

  • 序列化器基类 DRF 中所有的序列化器类都必须继承于序列化器基类(rest_framework.serializers.Serializer) 。

  • 模型序列化器基类 序列化器基类的子类,同时 DRF 中所有的序列化器类都必须继承于 rest_framework.serializers.ModelSerializer

序列化器的作用

  • 数据对象转换 实现序列化和反序列化。
  • 数据校验 在反序列化过程中对数据进行校验。

序列化器的组成

一个完整序列化器中应该包含三方面的内容:

转换的字段声明

客户端字段 = serializer.字段类型(字段校验项=字段值)

如果当前序列化器为模型序列化器,则需要声明调用的模型信息

# serializer.py
from rest_framework import serializers
class TestModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = 模型
        fields = 字段列表

验证字段的方法

验证字段合法性之后必须要将值返回(原值或者修改过的值)

模型的操作方法

重写 create()update() 两个方法,实现数据的插入和更新。

create

添加数据操作,添加数据以后,自动实现从字典变成模型对象的过程。

update

更新数据操作,添加数据以后,自动实现从字典变成模型对象的过程。

序列化器的使用

构造方法

TestSerializer(instance=None,data=empty,**kwargs)
  • 用于序列化时,将模型类对象传入 instance 参数;

  • 用于反序列化时,将要被反序列化的数据传入 data 参数;

  • 除了 instancedata 参数外,在构造 Serializer 对象时,还可以通过 context 参数额外添加数据,通过 context 添加的数据,可以通过 Serializer 对象的 context 属性获取;

数据校验

数据校验的方法:

字段选项

自定义报错信息,在字段选项中添加选项 error_messages

validate
验证一个字段
class TestSerializer(serializers.Serializer):
    def validate_<字段名>(self,value):
         pass
         return value
验证多个字段
class TestSerializer(serializers.Serializer):
    def validate(self,attrs):
        pass
        return attrs
validators

保存和更新数据

# serializer.py
from rest_framework import serializers
class TestSerializer(serializers.Serializer):
    def create(self,validated_data):
       pass
    def update(self,instance,validate_data):
       pass

Demo

模型

# models.py
class Student(models.Model):
    name = models.CharField(
        null=False,
        max_length=255,
        verbose_name='姓名'
    )
    age = models.IntegerField(
        null=False,
        verbose_name='年龄'
    )
    sex = models.IntegerField(
        null=False,
        verbose_name='性别'
    )
    active = models.BooleanField(
        # 默认值为 True
        default=True,
        verbose_name='是否活跃'
    )
    description = models.CharField(
        max_length=255,
        null=True,
        blank=True,
        verbose_name='描述'
    )
    date_joined = models.DateTimeField(
        default=timezone.now,
        verbose_name='加入时间'
    )

路由

# urls.py
from django.urls import path
from .views import StudentView

urlpatterns = [
    path('student/<str:pk>', StudentView.as_view()),
]

序列化

视图

views.py 中视图函数(使用 DRF)

# views.py
from rest_framework.views import APIView
from django.http import JsonResponse
from SerializerDemo.models import Student
from SerializerDemo.serializers import StudentSerializer
class StudentView(APIView):
    def get(self, request, pk):
        """
        序列化器,序列化阶段的调用
        """
        if pk == 'all':
            # 1、获取数据集
            student_list = Student.objects.all()
            # 2、实例化序列化器,得到序列化对象
            serializer = StudentSerializer(instance=student_list, many=True)
            # 3、调用序列化对象的data属性方法获取转换后的数据
            data = serializer.data
            # 4、响应数据
            return JsonResponse({'data': data, 'message': 'success'})
        else:
            query = Student.objects.filter(id=pk)
            if query.count():
                student = query.first()
                serializer = StudentSerializer(instance=student)
                data = serializer.data
                return JsonResponse({'data': data, 'message': 'success'})
            else:
                return JsonResponse({'message': 'ID不存在'})
序列化器
# serializers.py
from rest_framework import serializers
class StudentSerializer(serializers.Serializer):
    """
    完整的序列化类内部包含三部分的内容
    1、序列化转换的字段声明
    2、反序列化的校验器,即校验前端传入的字段
    3、反序列化模型操作的方法,create和update方法
    """
    id = serializers.IntegerField()
    date_joined = serializers.DateTimeField()
    name = serializers.CharField()
    age = serializers.IntegerField()
    active = serializers.BooleanField()
    sex = serializers.IntegerField()
    description = serializers.CharField()

    def update(self, instance, validated_data):
        pass

    def create(self, validated_data):
        pass

反序列化

视图
# views.py
from rest_framework.views import APIView
from django.http import JsonResponse
from SerializerDemo.models import Student
from SerializerDemo.serializers import StudentSerializer
import json

class StudentView(APIView):
	def post(self, request):
        """反序列化,采用字段选项来验证数据"""
        # 1、接收客户端提交的数据
        # 1.1 实例化序列化器,获取序列化对象
        data = json.dumps(request.body)
        # 1.2 调用序列化对象验证数据
        serializer = StudentSerializer(data=data)
        # 1.3 获取验证结果
        serializer.is_valid()  # 不抛出异常
        serializer.is_valid(raise_exception=True)  # 抛出异常
        # 2、操作数据
        pass
        # 3、返回数据
        return JsonResponse(serializer.validated_data)
        def put(self, request):
        """反序列化,采用字段选项来验证数据"""
        # 1、根据客户端提交的数据获取指定数据
        # 1.1 实例化序列化器,获取序列化对象
        pk = request.data.get('id', '')
        student = Student.objects.filter(pk=pk).first()
        data = json.dumps(request.body)
        # 1.2 调用序列化对象验证数据
        serializer = StudentSerializer(instance=student, data=data)
        # 1.3 获取验证结果
        serializer.is_valid(raise_exception=True)  # 抛出异常
        # 2、操作数据
        # 会根据实例化序列化器的时候是否传入instance属性来自动调用create或者update方法,如果传入instance属性,调用update方法,没有传入instance属性,调用create方法
        serializer.save()
        # 3、返回数据
        return JsonResponse(serializer.data)
序列化器
数据校验
def check_sex(value):
    """
    外部校验器 validator
    """
    if value not in [0, 1, 2]:
        raise serializers.ValidationError(
            detail='性别设置错误',
            code='check_sex'
        )
    return value


class StudentSerializer(serializers.Serializer):
    """
    完整的序列化类内部包含三部分的内容
    1、序列化转换的字段声明
    2、反序列化的校验器,即校验前端传入的字段
    3、反序列化模型操作的方法,create和update方法
    """
    # read_only=True,在客户端提交数据[反序列化阶段]不要求的字段
    id = serializers.IntegerField(read_only=True)
    date_joined = serializers.DateTimeField(read_only=True)
    # required=True,反序列化阶段必填
    name = serializers.CharField(required=True)
    # 最大值 max_value 和最小值 min_value
    age = serializers.IntegerField(
        max_value=100,
        min_value=0,
        error_messages={
            "min_value": "Age must older than 0",
            "max_value": "Age must younger than 100"
        }
    )
    # 默认值为 True
    active = serializers.BooleanField(default=True)
    # validator的值为列表,列表的成员为函数名,而不是函数的调用
    sex = serializers.IntegerField(validators=[check_sex])
    # 允许客户端不填写内容(None),或者值为 ""
    description = serializers.CharField(allow_null=True, allow_blank=True)

    def validate_name(self, data):
        """
        校验单个字段
        方法名必须以validate_<字段名>为名称,否则序列化器无法识别
        validate开头的方法,会自动被is_valid调用
        """
        if data in ["管理员", "超级管理员"]:
            raise serializers.ValidationError(
                detail="学生名字不能是管理员或者超级管理员",
                code="name"
            )

        return data

    def validate(self, attrs):
        """
        验证来自客户端的所有字段
        """
        if not attrs['active'] and attrs['description']:
            raise serializers.ValidationError(
                detail='非active学生需要添加描述',
                code='validate'
            )
        return attrs
数据保存和更新
    def update(self, instance, validated_data):
        """
        参数都是固定的,
        instance 实例化序列化器对象时,必须要传入的模型对象
        """
        for key, value in validated_data.items():
            setattr(instance, key, value)
        instance.save()
        return instance

    def create(self, validated_data):
        """
        保存数据
        """
        student = Student.objects.create(**validated_data)
        return student

补充说明

  • 在对序列化器进行 save() 保存时,可以额外传递数据,这些数据可以在 create()update() 中的 validated_data 参数中获取到

    serializer.save(owner=request.user)
    
  • 默认序列化器必须传递所有的 required 字段,否则会抛出校验异常,但是可以使用 partial 参数来允许部分字段更新
    更新 name,不需要校验其他字段,可以设置 partial=True

    serializer = StudentSerializer(student,data={'name':'xiaodong'},partial=True)
    
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值