上一章:
四、DRF序列化器create方法与update方法_做测试的喵酱的博客-CSDN博客
零、前提
项目表与接口表 models.py
class Projects(models.Model):
id = models.AutoField(primary_key=True, verbose_name='id主键', help_text='id主键')
name = models.CharField(max_length=20, verbose_name='项目名称', help_text='项目名称',
unique=True)
leader = models.CharField(max_length=10, verbose_name='项目负责人', help_text='项目负责人')
# c.使用default指定默认值(如果指定默认值后,在创建记录时,改字段传递,会使用默认值)
is_execute = models.BooleanField(verbose_name='是否启动项目', help_text='是否启动项目',
default=True)
# d.null=True指定前端创建数据时,可以指定该字段为null,默认为null=False,DRF进行反序列化器输入时才有效
# e.blank=True指定前端创建数据时,可以指定该字段为空字符串,默认为blank=False,DRF进行反序列化器输入时才有效
desc = models.TextField(verbose_name='项目描述信息', help_text='项目描述信息',
null=True, blank=True, default='')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间', help_text='更新时间')
class Meta:
# i.db_table指定创建的数据表名称
db_table = 'tb_projects'
# 为当前数据表设置中文描述信息
verbose_name = '项目表'
verbose_name_plural = '项目表'
# 项目表,默认根据id进行排序
ordering = ['id']
def __str__(self):
return f"项目名称:{self.name},项目负责人:{self.leader}"
class Interfaces(models.Model):
id = models.AutoField(primary_key=True, verbose_name='id主键', help_text='id主键')
name = models.CharField(verbose_name='接口名称', help_text='接口名称', max_length=20, unique=True)
tester = models.CharField(verbose_name='测试人员', help_text='测试人员', max_length=10)
# e.ForeignKey第一个参数为必传参数,指定需要关联的父表模型类
# 方式一:直接使用父表模型类的引用
# 方式二:可以使用'子应用名称.父表模型类名'(推荐)
projects = models.ForeignKey('miaoschool.Projects', on_delete=models.CASCADE,
verbose_name='所属项目', help_text='所属项目')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间', help_text='更新时间')
class Meta:
# db_table指定创建的数据表名称
db_table = 'tb_interfaces'
# 为当前数据表设置中文描述信息
verbose_name = '接口表'
verbose_name_plural = '接口表'
ordering = ['id']
def __str__(self):
return f"接口名称:{self.name}"
一、ModelSerializer 介绍
模型序列化器ModelSerializer 的作用,相比于模型类Serializer主要解决了两个问题
1、ModelSerializer 中,会自动生成 create 方法 与update方法
2、ModelSerializer 中,会自动生成模型类的所有字段,不需要手动一个一个的去写。
其他功能,与序列化器一致,包括联合校验,单字段校验。
定义模型序列化器类
1、继承serializers.ModelSerializer类或者其子类
2、需要在Meta内部类中指定model、fields、exclude类属性参数
3、model指定模型类(需要生成序列化器的模型类)
4、fields指定模型类中哪些字段需要自动生成序列化器字段
5、会给id主键、指定了auto_now_add或者auto_now参数的DateTimeField字段,添加read_only=True,仅仅只进行序列化输出
6、有设置unique=True的模型字段,会自动在validators列表中添加唯一约束校验<UniqueValidator
7、有设置default=True的模型字段,会自动添加required=False
8、有设置null=True的模型字段,会自动添加allow_null=True
9、有设置blank=True的模型字段,会自动添加allow_blank=True
1.1 模型序列化器ModelSerializer 应用
在项目中,一般是用的是ModelSerializer,而不是使用serializers.Serializer
ModelSerializer 不需要一个字段一个字段的去写,而是直接通过模型类做了映射。
class ProjectModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
fields = "__all__"
继承serializers.ModelSerializer
内部类Meta中,model设置映射的模型类
fields= 设置,需要做映射的字段,为 "__all__" 时,表示对模型类中所有的字段做了映射。
1.2 fields= 设置映射模型类的哪些字段
- fields = "__all__"
- fields = ('id', 'name', 'leader')
- exclude = ('create_time', 'update_time')
1.2.1 fields = "__all__" 映射模型类的所有字段
模型类中,所有的字段都需要做序列化处理时。使用
fields = "__all__"
class ProjectModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
fields = "__all__"
1.2.2 fields = ('id', 'name', 'leader') 映射部分字段
模型类中,只有部分字段都需要做序列化处理时。比如序列化处理只需要处理
id 、 name 、leader 这三个字段,其他字段全都忽略。使用fields = () ,
这是一个元组,当只有一个值时,需要加一个逗号 fields = ("id ",)
class ProjectModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
fields = ('id', 'name', 'leader')
1.2.3 exclude = ('create_time', 'update_time') 不处理部分字段
在Projects模型类中,有几个字段不需要做序列化的处理,剩余其他的字段都需要做序列化处理。
我们这里可以通过exclude 指定过滤不需要做序列化处理的字段。
exclude = ('create_time', 'update_time')
class ProjectModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
exclude = ('create_time', 'update_time')
1.3 views视图调用序列化器
class ProjectsView(View):
def post(self,request):
# 1、获取json参数并转化为python中的数据类型(字典)
try:
dic_data = json.loads(request.body)
except Exception as e:
return JsonResponse({'msg': '参数有误'}, status=400)
# 获取反序列化的实例对象
projects_serializer_obj = ProjectModelSerializer(data=dic_data)
# 对数据进行校验
# 校验不通过
if not projects_serializer_obj.is_valid():
return JsonResponse(projects_serializer_obj.errors, status=400)
projects_serializer_obj.save()
# 对创建的数据进行数据回显(序列化)
# serializer = StudentSerializer(instance=student)
return JsonResponse(projects_serializer_obj.data, status=201)
二、修改自动生成的序列化器字段
2.1 重新定义一个字段,来替换系统映射的字段
使用serializers.ModelSerializer ,序列化,处理所有的字段时,是根据models定义表字段的要求进行校验的。
如models.py中 中,模型类Projects 的name字段,只要求了max_length=20 只要求了最大长度,没有要求最小长度。
class Projects(models.Model):
id = models.AutoField(primary_key=True, verbose_name='id主键', help_text='id主键')
name = models.CharField(max_length=20, verbose_name='项目名称', help_text='项目名称',
unique=True)
在序列化器中,我们想要校验name字段的最小长度。可以通过重新定义name字段实现。
class ProjectModelSerializer(serializers.ModelSerializer):
name = serializers.CharField(label='项目名称', help_text='项目名称', max_length=20, min_length=5,
error_messages={
'min_length': '项目名称不能少于5位',
'max_length': '项目名称不能超过20位'
}, validators=[UniqueValidator(queryset=Projects.objects.all(), message='项目名称不能重复'),
)
class Meta:
model = Projects
fields = "__all__"
2.2 对系统自动生成的字段,进行微调
1、如果自动生成的序列化器字段,只有少量不满足要求,可以在Meta中extra_kwargs字典进行微调
2、将需要调整的字段作为key,把具体需要修改的内容字典作为value
举例:
class ProjectModelSerializer(serializers.ModelSerializer):
class Meta:
model = Projects
fields = "__all__"
extra_kwargs = {
'leader': {
'label': '负责人',
'max_length': 15,
'min_length': 2,
},
'name': {
'min_length': 5
}
}
2.3 批量需要设置read_only=True
可以将需要批量需要设置read_only=True参数的字段名添加到Meta中read_only_fields元组
read_only_fields = ('leader', 'is_execute', 'id')
三、 序列化器主表中,显示从表数据
在主表的序列化器中,增加从表数据的字段。
字段名称为 从表模型类小写名称_set
interfaces_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class ProjectModelSerializer(serializers.ModelSerializer):
interfaces_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Projects
fields = "__all__"
四、序列化器处理模型类中不存在的字段
如在Projecrs模型类中,不存在 的字段。(如token字段,在模型类中没有,但是在序列化器中需要处理这个字段)
1、在序列化器中,定义该字段
class ProjectModelSerializer(serializers.ModelSerializer):
token = serializers.CharField(read_only=True)
class Meta:
model = Projects
fields = "__all__"
2、views视图在调用序列化器时,传该字段的值 save(key=value)
serializer.save(token="abc")
3、在序列化器中,重写 create 函数。
提取多余字段,并将多余自动剔除
def create(self, validated_data):
"""
a.继承ModelSerializer之后,ModelSerializer中实现了create和update方法
b.一般无需再次定义create和update方法
c.如果父类提供的create和update方法不满足需要时,可以重写create和update方法,最后再调用父类的create和update方法
:param validated_data:
:return:
"""
token = validated_data.pop('token')
instance = super().create(validated_data)
return instance
整体代码:
class ProjectModelSerializer(serializers.ModelSerializer):
token = serializers.CharField(read_only=True)
class Meta:
model = Projects
fields = "__all__"
def create(self, validated_data):
token = validated_data.pop('token')
instance = super().create(validated_data)
return instance
五、重写create update方法
a.继承ModelSerializer之后,ModelSerializer中实现了create和update方法
b.一般无需再次定义create和update方法
c.如果父类提供的create和update方法不满足需要时,可以重写create和update方法,最后再调用父类的create和update方法
def create(self, validated_data):
"""
a.继承ModelSerializer之后,ModelSerializer中实现了create和update方法
b.一般无需再次定义create和update方法
c.如果父类提供的create和update方法不满足需要时,可以重写create和update方法,最后再调用父类的create和update方法
:param validated_data:
:return:
"""
validated_data.pop('myname')
validated_data.pop('myage')
instance = super().create(validated_data)
instance.token = "xxxxxxx"
return instance