一文了解DRF——ModelSerializer

一文了解DRF——ModelSerializer 在这篇文章中https://blog.csdn.net/2305_79295532/article/details/158928900我们讲过如何使用Serializer但是我们可以注意到每个字段我们都需要手动定义并且加上参数。那有没有一种办法可以实现自动定义字段而且最好是定义模型的时候加了什么字段什么参数序列化器就能生成类似或者一样的字段呢 有的兄弟有的 ——ModelSerializer阅读本文必须先去了解什么是Serializer也可查看我的文章其中有对Serializer详细的讲解目录一、ModelSerializer是什么1.1、定义1.2、 ModelSerializer 对比 Serializer二、使用ModelSerializer2.1 定义模型2.2 定义ModelSerializer2.3、在视图中使用ModelSerializer保存用户2.4、Apipost完成接口测试三、ModelSerializer拓展3.1、关于2.1、定义模型留下的坑问题一DRF 通过 字段映射表Field Mapping 元数据推断 自动生成序列化器字段。推断字段类型推断字段选项来自模型约束问题二null 影响数据库存储blank 影响输入验证ModelSerializer 分别映射为 allow_null 和 required/allow_blank。处理规则总结3.2、关于2.2、定义ModelSerializer留下的坑使用 read_only_fields 和 extra_kwargs一、ModelSerializer是什么1.1、定义ModelSerializer是 Django REST FrameworkDRF提供的一个序列化器基类它能自动根据指定的 Django 模型Model推断并生成对应的字段、验证规则以及默认的.create()和.update()方法从而将模型实例与 JSON 兼容的原生数据结构如字典相互转换极大减少样板代码适用于标准的模型 CRUD API 开发。简而言之1、ModelSerializer根据模型生成对应的字段2、ModelSerializer实现了createupdate方法用于操作数据库实现数据的增改。1.2、 ModelSerializer 对比 SerializerSerializer完全手动定义字段和逻辑灵活但重复适用于任意数据结构。ModelSerializer自动绑定 Django 模型自动生成字段、验证、保存逻辑适用于标准模型 CRUD。维度Serializer普通ModelSerializer继承关系rest_framework.serializers.BaseSerializerSerializer的子类是否依赖模型不依赖必须指定Meta.model字段定义完全手动声明每个字段自动从模型字段推断类型、max_length、null、blank等.create()/.update()必须自己实现自动生成调用Model.objects.create()和instance.save()验证规则全靠自定义validate_,validators自动继承模型约束•unique→ 唯一性验证•blankFalse→requiredTrue•nullFalse→allow_nullFalse适用数据源任意 Python 对象字典、聚合数据、非模型数据仅限 Django 模型实例或 QuerySet典型场景登录、注册、搜索、统计报表、第三方 API 适配用户管理、文章发布、商品 CRUD 等标准模型操作二、使用ModelSerializer接下来进入本文核心点——如何使用ModelSerializer 完成一个用户注册功能2.1 定义模型因为ModelSerializer根据模型生成字段所以定义模型就是第一步。定义模型对你来说可能很简单但是接下来这几个问题如果你都能答出来才算真的过关1.ModelSerializer根据模型字段会生成对应的字段那你说说到底怎么对应的生成了什么字段2.关于 null 和 blank这两个参数 ModelSerializer会怎么处理这两个问题的答案放在拓展中详细展开这里我们着重讲如何使用ModelSerializerfrom django.db import models from django.core.validators import RegexValidator # Create your models here. class User(models.Model): username models.CharField(用户名, nullFalse, blankFalse,max_length50) password models.CharField(密码, nullFalse,blankFalse,max_length15) mobile models.CharField(手机号, uniqueTrue, nullFalse,blankFalse,max_length11,validators[RegexValidator(r^1[3-9]\d{9}$, 请输入有效的中国大陆手机号)]) email models.CharField(邮箱, uniqueTrue, nullFalse,blankFalse,max_length20) avatar models.URLField(头像, blankTrue,nullTrue) bio models.TextField(个人简介, default这个人很帅什么都没有留下, blankTrue, max_length500) class Meta: verbose_name 用户信息 verbose_name_plural 用户信息 db_table user_profile2.2 定义ModelSerializer按照以下三步走step1定义 Meta类指定模型及fields列表step2根据具体业务可以选择新增自定义字段亦或者覆盖模型字段re_password新增字段 bio覆盖模型字段step3如有自定义字段需在validate方法中进行剔除Tips关于新增字段需在fields中声明ModelSerializer的fields列表决定了哪些字段会被包含在序列化器中。即使在类中声明了re_password ...如果它不在Meta.fields里DRF 会直接忽略它新增字段如果仅用于数据校验要定义validate方法进行字段剔除如需覆盖模型字段需要主动声明对于bio字段注册时无需用户填写故设置为只读关于Meta元类 如何定义的细节以及其他配置项将在 三、ModelSerializer扩展中展开from rest_framework import serializers from .models import User class RegisterSerializer(serializers.ModelSerializer): re_password serializers.CharField(requiredTrue,write_onlyTrue) bio serializers.CharField(read_onlyTrue) class Meta: model User fields [username, password, mobile, email, avatar, bio, re_password] def validate(self, attrs): # 进行密码校验 两次输入密码需一致 ...... # 数据库无该字段 也不用存 故剔除re_password attrs.pop(re_password) return attrs2.3、在视图中使用ModelSerializer保存用户使用ModelSerializer要严格按照以下步骤实例化序列化器传入数据调用is_valid方法校验数据只有通过校验才能进行save方法调用否则报错最后.data进行序列化返回from rest_framework.response import Response from rest_framework import status from .models import User # Create your views here. class RegisterAPIView(APIView): def post(self,request): # 传入数据 serializer RegisterSerializer(datarequest.data,context{request:request}) # 校验数据 serializer.is_valid(raise_exceptionTrue) # 保存数据 serializer.save() return Response(serializer.data,statusstatus.HTTP_201_CREATED)2.4、Apipost完成接口测试三、ModelSerializer拓展3.1、关于2.1、定义模型留下的坑1.ModelSerializer根据模型字段会生成对应的字段那你说说到底怎么对应的生成了什么字段2.关于 null 和 blank这两个参数 ModelSerializer会怎么处理问题一DRF 通过字段映射表Field Mapping 元数据推断自动生成序列化器字段。在ModelSerializer源码中有一个 serializer_field_mapping 的字典它定义了字段映射关系。可以点进源码查看其位于ModelSerializer类的最上面。下面是我整理的表格关于字段及字段选项的推断关系通过查阅这个表格能够完全明白模型定义的字段及约束会怎么生成到序列化器中推断字段类型Django 模型字段DRF 自动生成的 Serializer 字段关键参数推断CharField/TextFieldCharFieldmax_length,allow_blank not field.blankEmailFieldEmailField同上URLFieldURLField同上IntegerFieldIntegerFieldmin_value,max_value如有 validatorsFloatFieldFloatField—DecimalFieldDecimalField必须有max_digits,decimal_placesBooleanFieldBooleanField—DateFieldDateFieldauto_now/auto_now_add→read_onlyTrueDateTimeFieldDateTimeField同上ForeignKey/OneToOneFieldPrimaryKeyRelatedFieldquerysetmodel_field.related_model.objects.all()ManyToManyFieldPrimaryKeyRelatedField(manyTrue)同上FileField/ImageFieldFileField/ImageField—UUIDFieldUUIDField—推断字段选项来自模型约束模型字段属性→ Serializer 字段选项blankFalserequiredTrue,allow_blankFalse文本类blankTruerequiredFalse,allow_blankTruenullFalseallow_nullFalsenullTrueallow_nullTrueuniqueTrue添加UniqueValidatorchoices自动加ChoiceField验证default不自动设为 serializer 默认值需手动处理问题二null影响数据库存储blank影响输入验证ModelSerializer 分别映射为allow_null和required/allow_blank。null 指的是 数据库中对应的这个字段能不能存 null值blank指的是 前端传数据时对应的这个字段可以不传一个是数据库保存数据一个是前端传数据到后端。重点区别文本字段有空字符串 概念 → 所以需要allow_blank来限制不能传空字符串非文本字段没有空字符串 → 只能是null或有效值 → 所以只看required和allow_null处理规则总结模型字段类型模型中blankFalse→blankTrue→nullFalse→nullTrue→文本类(CharField,TextField)序列化器中requiredTrueallow_blankFalserequiredFalseallow_blankTrueallow_nullFalseallow_nullTrue非文本类(IntegerField,DateTimeField,ForeignKey)序列化器中requiredTruerequiredFalseallow_nullFalseallow_nullTrue3.2、关于2.2、定义ModelSerializer留下的坑关于Meta元类 如何定义的细节以及其他配置项在2.2中 我们粗略的讲了下使用Meta元类 指定模型及需要生成的字段。除了这两个外Meta元类还可以指定很多参数以下是ModelSerializer.Meta的常用配置项这里看着有很多但实际开发时经常使用的还是头两个有时为了节省代码可能使用read_only_fieldsextra_kwargs。所以将重心放在这四个上面即可。以后遇到了对应场景再去学习了解也不迟属性类型说明示例modelModel类指定关联的 Django 模型仅ModelSerializer及其子类需要model Userfieldslist[str]或__all__指定要序列化的字段名列表。•__all__表示包含所有模型字段• 可包含自定义字段需在类中声明fields [id, username, email]excludelist[str]排除某些字段不能与fields同时使用exclude [password, is_staff]read_only_fieldslist[str]指定只读字段反序列化时忽略仅用于输出read_only_fields [created_at, id]extra_kwargsdict为字段提供额外参数如write_only,required,min_length等适用于模型字段extra_kwargs { password: {write_only: True},email: {required: True, min_length: 5}}validatorslist[callable]添加跨字段对象级验证器作用于整个validated_datadepthint自动展开外键/关系字段的嵌套层级仅用于读取/序列化不用于写入使用 read_only_fields 和 extra_kwargs还是以该代码为例我们来讲清楚注意事项extra_kwargs是方便开发者不用为了新增字段配置而去重新定义字段。前提是该字段是模型中已定义read_only_fields 用于设置fields列表中那些字段只读也是为了简化开发。对字段无要求。配置能否用于非模型字段建议使用场景read_only_fields✅ 可以任何你想设为只读的字段无论来源extra_kwargs❌不可以仅用于模型字段的快捷配置避免显式重写字段from rest_framework import serializers from .models import User class RegisterSerializer(serializers.ModelSerializer): re_password serializers.CharField(requiredTrue,write_onlyTrue) # bio serializers.CharField(read_onlyTrue) #下方配置了read_only_fields 故取消注释 class Meta: model User fields [username, password, mobile, email, avatar, bio, re_password] # 配置了这个 那么上面的bio就可以注释掉 read_only_fields [bio] # 只能作用于model中定义的字段 extra_kwargs { password: {write_only:True}, # password 是模型字段 有效 re_password: {write_only:True, required:True} # re_password 不是模型中的字段 无效 } def validate(self, attrs): # 进行密码校验 两次输入密码需一致 ...... # 数据库无该字段 也不用存 故剔除re_password attrs.pop(re_password) return attrs