django 3.2.13

一、序列化和反序列化

安装:pip install djangorestframework

序列化:序列化就是从数据库里面取出数据—>并且把数据格式改为能直接返回的格式(如json、xml)。补充:django rest引入这一步的目的就是为了简便格式的处理,这样能少写很多繁琐的代码

反序列化:反序列化就是用户向服务器发送参数(如json)—>变为数据库可以识别的,中间还要经过数据的验证

1.继承serializers.Serializer

1.1 初始化配置

过程:对应模型models.py里面的模型在serializers.py进行创建,此步为了能够让serializers识别模型

App/models.py

class User(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

App/serializers.py
注意:此处写的语法规则与定义模型时类似但也有不同,如下面是此参数说明

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID')
    name = serializers.CharField(max_length=20,label='名称')

字段

字段构造方式

BooleanField

BooleanField()

NullBooleanField

NullBooleanField()

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(maxlength=50, min_length=None, allow_blank=False)正则字段,验证正则模式 [a-zA-Z0-9-]+

URLField

URLField(max_length=200, min_length=None, allow_blank=False)

UUIDField

UUIDField(format=‘hex_verbose’)format:① ‘hex_verbose’ 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"② ‘hex’ 如 "5ce0e9a55ffa654bcee01238041fb31a"③’int’ - 如: "123456789012312313134124512351145145114"④’urn’ 如: “urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a”

IPAddressField

IPAddressField(protocol=‘both’, unpack_ipv4=False, **options)

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)choices与Django的用法相同

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_lenght

最小长度

allow_blank

是否允许为空

trim_whitespace

是否截断空白字符

max_value

最小值

min_value

最大值

read_only

表明该字段仅用于序列化输出,默认False

write_only

表明该字段仅用于反序列化输入,默认False

required

表明该字段在反序列化时必须输入,默认True

default

反序列化时使用的默认值

allow_null

表明该字段是否允许传入None,默认False

validators

该字段使用的验证器

error_messages

包含错误编号与错误信息的字典

label

用于HTML展示API页面时,显示的字段名称

help_text

用于HTML展示API页面时,显示的字段帮助提示信息

1.2 序列化

核心:Serializer(instance=None, data=empty, **kwarg) # 给instance值就是使用序列化,给data值就是使用反序列化

新建:Serializer(data=requestData) 更新:Serializer(instance, data=requestData) 获取:Serializer(instance)

代码:

user= User.objects.get(id=2)
serializer = UserSerializer(instance=user)# 进行序列化
print(serializer.data)#{'a':55,'c':999}
1.2.1 删除不想要的字段

解释:当serializer.data中某些字段不想要时,就可以向删除字典内容一样将其删除

user= User.objects.get(id=2)
serializer = UserSerializer(instance=user)# 进行序列化
a = serializer.data
del a['username']
# 这时候返回a就可以,里面自然不会包括username字段
1.2.2 转换格式

注意:如果要被序列化的是包含多条数据的查询集,添加many=True,如:serializer = UserSerializer(instance=user,many=True)

from testWeb.models import User
from testWeb.serializers import UserSerializer
user= User.objects.get(id=2)
serializer = UserSerializer(instance=user)# 进行序列化
print(serializer.data) # 获取序列化从数据库提取出来的数据

# 遇到关联的对象数据不是只有一个,而是包含多个数据,添加many=True
serializer = UserSerializer(instance=user,many=True)# 进行序列化

# 使用外键的对象,则需要用外键对应serializer.py里面的序列类
① 错例子
o = Student.objects.get(id=3).foreign # Student关联Teacher
oo = StudentSerializer(o) # 此处有问题应该为Teacher关联类
② 正确例子
o = Student.objects.get(id=3).foreign # Student关联Teacher
oo = TeacherSerializer(o) # 正确

外键问题
缘由:django rest在把models模型转换为serializer序列类时,大部分属性都和model一样,但是外键这里进行单独处理

  1. 值为id
h = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
  1. 值为models.py自己设置的__str__的返回值
h = serializers.StringRelatedField(label='图书')
  1. 值关联对象的数据值
h = BookInfoSerializer() # 此为关联对象

1.3 反序列化

1.3.1 验证

验证流程:

>>> data = {"name":"5559"}
>>> response = TeacherSerializer(data=data) 
>>> response.is_valid()                     
True
>>> response.save() 
<Teacher: 5559>

# response.errors 查看报错内容
>>> response.errors
{'name': [ErrorDetail(string='该字段是必填项。', code='required')]}

# 验证报错
>>> response.is_valid(raise_exception=True) # 当发送错误直接报错
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Loser\AppData\Local\Programs\Python\Python38\lib\site-packages\rest_framework\serializers.py", line 235, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'name': [ErrorDetail(string='该字段是必填项。', code='required')]}

验证规则:

  1. validate_<自己定义的名字>

serializers.py

class TeacherSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID')
    name = serializers.CharField(max_length=20,label='名称')
    def validate_name(self,value):
        if value != '853':
            raise serializers.ValidationError("853失败")
        else:
            return True # 必须要提供返回值
>>> data ={ "name":"859"}            
>>> o = TeacherSerializer(data=data) 
>>> o.is_valid(raise_exception=True) 
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Loser\AppData\Local\Programs\Python\Python38\lib\site-packages\rest_framework\serializers.py", line 235, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'name': [ErrorDetail(string='853失败', code='invalid')]}
  1. validate(多字段一同验证)

serializers.py

class TeacherSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='ID')
    name = serializers.CharField(max_length=20,label='名称')
    
    def validate(self,data):
        if data['name'] != '853':
            raise serializers.ValidationError("853失败")
        else:
            return True # 必须要提供返回值
>>> data ={ 'name':"859"}            
>>> o = TeacherSerializer(data=data)   
>>> o.is_valid(raise_exception=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\Loser\AppData\Local\Programs\Python\Python38\lib\site-packages\rest_framework\serializers.py", line 235, in is_valid
    raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'non_field_errors': [ErrorDetail(string='853失败', code='invalid')]}
1.3.2 转换格式

解释:当数据被验证后,需要自己写入create()和update()函数,当你执行save()时,其会帮你判断执行create()还是update(),ModelSerializer包含默认的create()和update()的实现

# save()函数源码
	def save(self, **kwargs):
		validated_data = {**self.validated_data, **kwargs}
		if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
        else:
            self.instance = self.create(validated_data)
            assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )
	# create()自定义返回一个数据给save()
    def create(self, validated_data):
        """新建"""
        return Teacher(**validated_data)
        
	# update()自定义返回一个数据给save()
    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.btitle = validated_data.get('btitle', instance.btitle)
        instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
        instance.bread = validated_data.get('bread', instance.bread)
        instance.bcomment = validated_data.get('bcomment', instance.bcomment)
        return instance

2.继承serializers.ModelSerializer

介绍:与Serializer功能一致,但代码更精简(常用)

区别:

  1. 基于模型类自动生成一系列字段
  2. 基于模型类自动为Serializer生成validators,比如unique_together
  3. 包含默认的create()和update()的实现

2.1 初始化配置(区别)

过程:基于模型类自动生成一系列字段

App/models.py

class Teacher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

App/serializers.py

class TeacherSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = Teacher
        fields = '__all__'

指定字段:

  1. fields:来明确字段,__all__表名包含所有字段或者写明具体哪些字段
class Meta:
        model = Teacher
        fields = ('id', 'like', 'go')
  1. exclude:明确排除改字段别的都要
class Meta:
        model = Teacher
        exclude = ('image',)
  1. extra_kwargs:添加或修改原有的选项参数
extra_kwargs = {
            'go': {'min_value': 5, 'required': True},
            'like': {'min_value': 5, 'required': True},
        }
  1. 自定义添加
class StudentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = '__all__'
        name = serializers.CharField(max_length=20, label='名称') # 自己给其新增
        extra_kwargs={
            'passwd':{'required':False},
            'time':{'required':False}
        }

2.2 序列化(区别)

解释:大体类似无明显区别

2.3 反序列化(区别)

解释:ModelSerializer额外提供了默认的create()和update()的方法,用来新建与更新数据,而serializers.Serializer也有默认的create()和update()的方法,但是没有任何代码需要自己书写

使用:

① save
>>> data = {"name":"85999"}
>>> r = TeacherSerializer(data=data) 
>>> r.is_valid()
True
>>> r.save()
<Teacher: 85999>