Django REST Framework(DRF)框架之Serializer序列化器的使用

Django REST Framework框架

概述

Django REST Framework(简称DRF)是基于Django Web框架的一个开源的Web API框架。它提供了一组用于快速构建Web API的工具和库,包括序列化器、认证、权限、视图、路由和文档化等功能。

DRF的主要特点包括:

提供了强大的序列化器,可以将模型对象序列化为JSON等格式,并支持反序列化

提供了多种认证方式,包括基本认证、Token认证、OAuth认证等

提供了多种权限校验方式,包括基于角色的权限校验、基于对象的权限校验等

提供了多种视图类,包括基于函数的视图、基于类的视图、通用视图等

提供了路由功能,可以轻松地将URL映射到对应的视图

可扩展性,插件丰富

DRF官方:https://www.django-rest-framework.org/

GitHub:https://github.com/encode/django-rest-framework

安装DRF框架

DRF框架依赖于Django,需先安装Django环境。

pip install djangorestframework

注册DRF

在Django项目中使用DRF框架进行开发时,需要将rest_framework在INSTALLED_APPS中进行注册。

INSTALLED_APPS = [
    'rest_framework',
]

字段类型与选项参数

字段类型

字段 字段构造方式 描述
BooleanField BooleanField() 布尔类型,通常用于表示真假数据
NullBooleanField NullBooleanField() 用于表示布尔类型的数据,可以包含三种值:True、False和Null。它可以自动将输入的字符串转换为布尔类型,并支持Null值
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) 字符串类型,通常用于表示文本数据
EmailField EmailField(max_length=None, min_length=None, allow_blank=False) 电子邮件类型,通常用于表示电子邮件地址
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False) 用于表示正则表达式类型的数据。它可以自动验证输入的字符串是否符合指定的正则表达式格式
SlugField SlugField(max_length=50, minlength=None, allow_blank=False) 是CharField的一个子类,通常用于表示URL中的短标识符。它可以自动将输入的字符串转换为URL安全的格式
URLField URLField(max_length=200, min_length=None, allow_blank=False) URL类型,通常用于表示URL地址
UUIDField UUIDField(format=‘hex_verbose’)
hex_verbose、 hex、int、urn
用于表示UUID(通用唯一识别码)类型的数据。它可以自动验证输入的字符串是否符合UUID格式,并将其转换为UUID对象
IPAddressField IPAddressField(protocol=‘both’, unpack_ipv4=False, **options) 用于表示IP地址类型的数据。它可以自动验证输入的字符串是否符合IP地址格式,并将其转换为IP地址对象
IntegerField IntegerField(max_value=None, min_value=None) 整数类型,通常用于表示数字数据
FloatField FloatField(max_value=None, min_value=None) 浮点数类型,通常用于表示小数数据
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits: 最多位数
decimal_palces: 小数点位置
高精度十进制数类型,通常用于表示货币等需要精确计算的数据
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) 日期时间类型,通常用于表示时间戳等时间数据
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None) 日期类型,通常用于表示日期数据
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None) 时间类型,通常用于表示时间数据
DurationField DurationField() 用于表示时间间隔类型的数据,可以表示一段时间的长度。它可以自动将输入的字符串转换为时间间隔类型
ChoiceField ChoiceField(choices) 选择类型,可以定义一个选择列表,用于表示一组固定的选项
MultipleChoiceField MultipleChoiceField(choices) 用于表示多选框类型的数据。它可以定义一个选项列表,用于表示可选的选项
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) 文件类型,通常用于表示文件数据
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) 图像类型,通常用于表示图片数据
ListField ListField(child=, min_length=None, max_length=None) 列表类型,可以用于表示一个列表数据
DictField DictField(child=) 字典类型,可以用于表示一个字典数据

选项参数

max_length和min_length是针对字符串类型的参数;max_value和min_value是针对数字类型的参数。

参数名称 作用
max_length 最大长度
min_length 最小长度
max_value 最大值
min_value 最小值

无论哪种字段类型都可以使用以下可选参数。

参数名称 说明
read_only 默认False 。用于指定字段是否只能用于序列化输出,不能用于反序列化输入。通常用于表示只读数据,例如时间戳等。在反序列化输入时,该字段的值会被忽略。
write_only 默认False 。 用于指定字段是否只能用于反序列化,不能用于序列化输出。通常用于表示敏感数据,例如密码等。在序列化输出时,该字段的值会被忽略。
required 表明该字段在反序列化时必须输入,默认True
default 序列化和反序列化时使用的默认值
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
allow_blank 设置字段是否允许为空白字符串。如果设置为True,反序列化时如果该字段的值为空白字符串会被认为是有效值
validators 设置字段的验证器。验证器是一个可调用对象,用于验证输入的数据是否符合要求。

定义序列化器类的字段时,如果没有指定read_only和write_only,则这两个参数默认值都为False,表明对应的字段既在序列化时使用,也在反序列化时使用

序列化器的定义与使用

定义序列化器类

序列化器类的定义格式:

from rest_framework import serializers

class 序列化器类名(serializers.Serializer):
    # 序列化器字段 = serializers.字段类型(选项参数)

新建serializers.py文件保存某应用的序列化器类

from rest_framework import serializers

# 用户类
class User(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
    name = serializers.CharField()
    age = serializers.IntegerField()

基本使用

序列化

if __name__ == '__main__':
    # 创建User对象
    user = User(name='test', age=22)

    # 将user对象序列化为:{'name': 'test', 'age': 22}
    serializer = UserSerializer(user)

    # 获取序列化之后的数据
    serializerData = serializer.data
    print(serializerData)

反序列化与数据校验

if __name__ == '__main__':
    data = {
    
    'name': 'test', 'age': 22}

    # 对data的数据进行反序列化
    serializer = UserSerializer(data=data)

    # 调用is_valid进行数据校验,成功返回True,失败返回False
    valid = serializer.is_valid()
    print(valid)
    
    # 获取校验失败之后的错误提示信息
    errors = serializer.errors
    print(errors)

    # 获取校验通过之后的数据
    user = serializer.validated_data
    print(user)

序列化操作

Django初始化

编辑子应用下的tests.py文件,需要使用Django的东西,添加Django初始化代码

# 设置Django运行所依赖的环境变量
import os

from django.test import TestCase

from apps.user.models import User
from apps.user.serializers import UserSerializer

if not os.environ.get('DJANGO_SETTINGS_MODULE'):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')

# 让Django进行一次初始化
import django

序列化单个对象

class User(models.Model):
    name = models.CharField(max_length=6, unique=True, verbose_name='姓名')
    age = models.IntegerField(default=0, verbose_name='年龄')

    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name
# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6)
    age = serializers.IntegerField(label="年龄")

# 设置Django运行所依赖的环境变量
import os

from django.test import TestCase

from apps.user.models import User
from apps.user.serializers import UserSerializer

if not os.environ.get('DJANGO_SETTINGS_MODULE'):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')

# 让Django进行一次初始化
import django

django.setup()


class MyTest(TestCase):
    # 查询User
    user = User.objects.get(id=1)
    # 使用序列化器对象
    serializer = UserSerializer(user)
    # 获取序列化后的数据
    data = serializer.data
    print(data)
{
    
    'name': 'Django', 'age': 20}

序列化多个对象

当要被序列化的是包含多条数据的查询集QuerySet或list,可以通过添加many=True参数说明。

class MyTest(TestCase):
    # 查询User
    user = User.objects.all()
    # 使用序列化器对象
    serializer = UserSerializer(user, many=True)
    # 获取序列化后的数据
    data = serializer.data
    print(data)
[OrderedDict([('name', 'Django'), ('age', 20)]), OrderedDict([('name', 'Python'), ('age', 30)])]

关联对象嵌套序列化

如果在序列化对象数据时,需要将其关联的对象一并序列化,则定义序列化器类的字段时,需要定义对应的关联对象嵌套序列化字段。对于关联字段,有3种定义方式。

如果一个对象关联的对象有多个,在序列化器类中定义嵌套序列化字段时,需要多添加一个many=True参数。

from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=6, unique=True, verbose_name='姓名')
    age = models.IntegerField(default=0, verbose_name='年龄')

    class Meta:
        db_table = 'tb_user'
        verbose_name = '用户'
        verbose_name_plural = verbose_name


class Car(models.Model):
    TYPE_CHOICES = (
        (0, '轿车'),
        (1, 'SUV')
    )
    name = models.CharField(max_length=8, unique=True, verbose_name='名称')
    price = models.DecimalField(max_digits=5, decimal_places=2, default=0, verbose_name='价格')
    type = models.SmallIntegerField(choices=TYPE_CHOICES, verbose_name='类型')
    user = models.ForeignKey(to=User, on_delete=models.CASCADE, verbose_name="用户")

    class Meta:
        db_table = 'tb_car'
        verbose_name = '车辆'
        verbose_name_plural = verbose_name

# 用户序列化器类:UserSerializer
class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6)
    age = serializers.IntegerField(label="年龄")
    
# 车辆序列化器类
class CarSerializer(serializers.Serializer):
    TYPE_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名字', max_length=8)
    price = serializers.DecimalField(label='价格', max_digits=5, decimal_places=2, default=0)
    type = serializers.ChoiceField(choices=TYPE_CHOICES, label='类型', required=False)

PrimaryKeyRelatedField

将关联对象序列化为关联对象的主键。指明字段时需要包含read_only=True或者queryset参数:

1.指定read_only=True参数时,该字段仅在序列化时使用。

car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', read_only=True,many=True)
class MyTest(TestCase):
    # 查询User
    user = User.objects.get(id=1)
    # user对象序列化
    serializer = UserSerializer(user)
    # 获取序列化之后的数据
    serializerData = serializer.data
    print(serializerData)
{
    
    'name': 'Django', 'age': 22, 'car_set': [1, 2]}

2.指定queryset参数时,将被用作反序列化时参数校验使用。

#car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', read_only=True,many=True)
car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', queryset=Car.objects.all(),many=True)
{
    
    'name': 'Django', 'age': 22, 'car_set': [1, 2]}

使用关联对象的序列化器

使用指定的序列化器类将关联对象进行序列化。

class CarSerializer(serializers.Serializer):
    TYPE_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    name = serializers.CharField(label='名字', max_length=8)
    price = serializers.DecimalField(label='价格', max_digits=5, decimal_places=2, default=0)
    type = serializers.ChoiceField(choices=TYPE_CHOICES, label='类型', required=False)

class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6)
    age = serializers.IntegerField(label="年龄")
	car_set = CarSerializer(many=True)    
{
    
    'name': 'Django', 'age': 22, 'car_set': [OrderedDict([('id', 1), ('name', '奥迪'), ('price', '99.00'), ('type', 1)]), OrderedDict([('id', 2), ('name', '宝马'), ('price', '88.00'), ('type', 2)])]}

StringRelatedField

将关联对象序列化为关联对象模型类__str__方法的返回值。

class Car(models.Model):
    TYPE_CHOICES = (
        (0, '轿车'),
        (1, 'SUV')
    )
    name = models.CharField(max_length=8, unique=True, verbose_name='名称')
    price = models.DecimalField(max_digits=5, decimal_places=2, default=0, verbose_name='价格')
    type = models.SmallIntegerField(choices=TYPE_CHOICES, verbose_name='类型')
    user = models.ForeignKey(to=User, on_delete=models.CASCADE, verbose_name="用户")

    class Meta:
        db_table = 'tb_car'
        verbose_name = '车辆'
        verbose_name_plural = verbose_name

    def __str__(self):
        return "name:%s price:%s" % (self.name, self.price)
class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6)
    age = serializers.IntegerField(label="年龄")
    car_set = serializers.StringRelatedField(label='拥有车辆', many=True)
{
    
    'name': 'Django', 'age': 22, 'car_set': ['name:奥迪 price:99.00', 'name:宝马 price:88.00']}

反序列化操作

数据校验

数据校验可以调用is_valid()方法,会根据对应序列化类字段的类型以及一些选项参数对data中的数据进行校验。

调用is_valid进行数据校验时,除了一些基本的默认验证行为,还可以补充一些验证行为,有以下三种方法。

is_valid()

if __name__ == '__main__':
    # User
    user = {
    
    'name': 'test', 'age': 22}

    # 创建序列化器对象,{
    
    'name': 'test', 'age': 22}进行反序列化
    serializer = UserSerializer(data=user)

    # 数据校验:成功返回True,失败返回False
    # 会根据对应序列化类字段的类型以及一些选项参数对data中的数据进行校验
    valid = serializer.is_valid()
    print(valid)

    errors = serializer.errors
    print(errors)
    
    # 获取校验成功之后的数据
    data = serializer.validated_data
    print(data)

validators

针对指定序列化器字段添加validators选项参数补充校验

def age_validator(value):
    if value < 18:
        raise serializers.ValidationError("未成年用户禁止操作")


# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6, )
    age = serializers.IntegerField(label="年龄", validators=[age_validator])


if __name__ == '__main__':
    # User
    user = {
    
    'name': 'test', 'age': 17}

    # 创建序列化器对象,{
    
    'name': 'test', 'age': 22}进行反序列化
    serializer = UserSerializer(data=user)

    # 数据校验:成功返回True,失败返回False
    valid = serializer.is_valid()
    print(valid)

    errors = serializer.errors
    print(errors)

    # 获取校验成功之后的数据
    data = serializer.validated_data
    print(data)
False
{
    
    'age': [ErrorDetail(string='未成年用户禁止操作', code='invalid')]}
{
    
    }

validate_<field_name>

在序列化器类中定义特定方法validate_<field_name>,针对特定字段进行补充验证

class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6, )
    age = serializers.IntegerField(label="年龄")

    def validate_age(self, value):
        if value < 18:
            raise serializers.ValidationError("未成年用户禁止操作")
        return value
if __name__ == '__main__':
    # User
    user = {
    
    'name': 'test', 'age': 17}

    # 创建序列化器对象,{
    
    'name': 'test', 'age': 22}进行反序列化
    serializer = UserSerializer(data=user)

    # 数据校验:成功返回True,失败返回False
    valid = serializer.is_valid()
    print(valid)

    errors = serializer.errors
    print(errors)

    # 获取校验成功之后的数据
    data = serializer.validated_data
    print(data)
False
{
    
    'age': [ErrorDetail(string='未成年用户禁止操作', code='invalid')]}
{
    
    }

validate

在序列化器类中定义validate方法针对多个字段的内容进行补充验证,

class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6, )
    age = serializers.IntegerField(label="年龄")

    def validate(self, attrs):
        age = attrs['age']
        if age < 18:
            raise serializers.ValidationError("未成年用户禁止操作")
        return attrs
# 设置Django运行所依赖的环境变量
import os

from django.test import TestCase

from apps.user.models import User
from apps.user.serializers import UserSerializer

if not os.environ.get('DJANGO_SETTINGS_MODULE'):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')

# 让Django进行一次初始化
import django

django.setup()
class MyTest(TestCase):
    # User
    user = {
    
    'name': 'test', 'age': 17}

    # 创建序列化器对象,{
    
    'name': 'test', 'age': 22}进行反序列化
    serializer = UserSerializer(data=user)

    # 数据校验:成功返回True,失败返回False
    valid = serializer.is_valid()
    print(valid)

    errors = serializer.errors
    print(errors)

数据保存

1.在数据校验通过后,想基于validated_data完成数据对象的创建,可以通过序列化器对象.save()进行数据的保存。

2.在save方法内部会调用序列化器类的create或update方法,可以在create方法中实现数据新增,update方法中实现数据更新。

3.创建序列化器对象的时候,如果没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。

# 用户序列化器类
class UserSerializer(serializers.Serializer):
    name = serializers.CharField(label='姓名', max_length=6, )
    age = serializers.IntegerField(label="年龄")

    # 新建
    def create(self, validated_data):
        user = User.objects.create(**validated_data)
        return user

    # 更新,instance:更新的对象实例
    def update(self, instance, validated_data):
        instance.name = validated_data.get('name', instance.name)
        instance.age = validated_data.get('age', instance.age)
        instance.save()
        return instance
# 设置Django运行所依赖的环境变量
import os

from django.test import TestCase

from apps.user.models import User
from apps.user.serializers import UserSerializer

if not os.environ.get('DJANGO_SETTINGS_MODULE'):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')

# 让Django进行一次初始化
import django

django.setup()

class MyTest(TestCase):
    # 新增
    user = {
    
    'name': 'Django', 'age': 22}
    serializer = UserSerializer(data=user)
    serializer.is_valid()
    # 调用序列化器类的create方法,实现新增
    serializer.save()
class MyTest(TestCase):
    # 更新
    user = User.objects.get(id=2)
    data = {
    
    'name': 'Java', 'age': 20}
    serializer = UserSerializer(user, data=data)
    serializer.is_valid()
    # 调用序列化器类的update方法,实现更新
    serializer.save()

ModelSerializer的使用

如果序列化器类对应Django某个模型类,则定义序列化器类时,可直接继承ModelSerializer。

ModelSerializer是Serializer类的子类,相对于Serializer,提供额外功能:

基于模型类字段自动生成序列化器类的字段

包含默认的create()和update()方法的实现

基本使用

创建一个UserSerializer类

# 用户序列化器类
class UserSerializer(serializers.ModelSerializer):
    class Meta:
    	# model:指明序列化器类对应的模型类
        model = User
        # fields:指明依据模型类的哪些字段生成序列化器类的字段,__all__表明包含所有字段
        fields = '__all__'

执行python manage.py shell命令,进入shell窗口,执行如下命令查看序列化器对象自动生成的具体字段

>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(label='姓名', max_length=6, validators=[<UniqueValidator(queryset=User.objects.all())>])
    age = IntegerField(label='年龄', max_value=2147483647, min_value=-2147483648, required=False)

指定字段

1.使用fields指明依据模型类的哪些字段生成序列化器类的字段,__all__表明包含所有字段,也可以指明具体哪些字段

class UserSerializer(serializers.ModelSerializer):
	class Meta:
	    # model:指明序列化器类对应的模型类
	    model = User
	    # fields:指明依据模型类的哪些字段生成序列化器类的字段
	    fields = ('id', 'name')

执行quit()退出shell,再执行python manage.py shell命令,进入shell窗口,执行查看

>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(label='姓名', max_length=6, validators=[<UniqueValidator(queryset=User.objects.all())>])

2.使用exclude可以指明排除哪些字段

class UserSerializer(serializers.ModelSerializer):
	class Meta:
	    model = User
	    exclude = ('name',)      

3.通过read_only_fields指明只读字段,即仅用于序列化的字段。

class UserSerializer(serializers.ModelSerializer):
	class Meta:
	    model = User
	    fields = ('id', 'name', 'age')
	    read_only_fields = ('id', 'name')

添加额外参数

可以使用extra_kwargs参数为自动生成的序列化器类字段添加或修改原有的选项参数。

class UserSerializer(serializers.ModelSerializer):
	class Meta:
	    model = User
	    fields = ('id', 'name', 'age')
	    extra_kwargs = {
    
    
	        'name': {
    
    'max_length': 3, 'required': True},
	        'age': {
    
    'min_value': 18, 'required': True},
	    }

添加或修改原有的选项参数:

>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    name = CharField(label='姓名', max_length=3, required=True, validators=[<UniqueValidator(queryset=User.objects.all())>])
    age = IntegerField(label='年龄', max_value=2147483647, min_value=18, required=True)

使用示例

re_path(r'^test/$', views.TestView.as_view(), name='test'),
from django.http import JsonResponse
from apps.users.models import User
from apps.users.serializers import UserSerializer
from django_redis.serializers import json

class TestView(View):
    def get(self, request):
        queryset = User.objects.all()
        # 序列化
        serializer = UserSerializer(queryset, many=True)

        return JsonResponse(serializer.data, safe=False)

    def post(self, request):
        json_bytes = request.body
        json_str = json_bytes.decode()
        user_dict = json.loads(json_str)

        # 反序列化-数据校验
        serializer = UserSerializer(data=user_dict)
        serializer.is_valid(raise_exception=True)

        # 反序列化-数据保存
        serializer.save()

        return JsonResponse(serializer.data, status=201)
 re_path(r'^test/(?P<id>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(View):

    def get(self, request, pk):
        try:
            user = User.objects.get(pk=pk)
        except User.DoesNotExist:
            raise Http404

        serializer = UserSerializer(user)

        return JsonResponse(serializer.data)

    def put(self, request, pk):
        try:
            user = User.objects.get(pk=pk)
        except User.DoesNotExist:
            return HttpResponse(status=404)

        json_bytes = request.body
        json_str = json_bytes.decode()
        user_dict = json.loads(json_str)

        # 反序列化-数据校验
        serializer = UserSerializer(user, data=user_dict)
        serializer.is_valid(raise_exception=True)

        # 反序列化-数据保存
        serializer.save()

        return JsonResponse(serializer.data)

    def delete(self, request, pk):
        try:
            user = User.objects.get(pk=pk)
        except User.DoesNotExist:
            return HttpResponse(status=404)

        user.delete()

        return HttpResponse(status=204)

猜你喜欢

转载自blog.csdn.net/qq_38628046/article/details/129866800