如何选择赣州网站建设,wordpress 分类 如何,建设网站需要会什么,apple网站模板文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结#xff1a; 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验序… 文章目录 一、Request对象源码分析区分原生request和新生request新的request还能像原来的reqeust一样使用吗源码片段分析总结 二、DRF之序列化组件序列化介绍序列化步骤序列化组件的基本使用反序列化基本使用反序列化的新增反序列化的新增删除单条 反序列化的校验序列化器常用字段和字段参数常用字段类常用字段参数 序列化器-source的使用source序列化自有字段和关联字段的区别 定制字段的两种方式反序列化之保存数据新增修改 反序列化之数据校验ModelSerializer的使用使用方法总结 一、Request对象源码分析 在上一篇博客中最后分析APIView时我们分析出继承了APIView的视图以后request都是新的request了是DRF提供的Request的对象 区分原生request和新生request 原生requestdjango.core.handlers.wsgi.WSGIRequest新生requestfrom rest_framework.request import Request原生request可以在新生request._request中获取新的request还能像原来的reqeust一样使用吗 用起来屎一样的新的request只是在原来的request基础上添加了一些功能并不影响基础功能的使用其本质就是类似装饰器print(request.method) # getprint(request.path) # /movies/print(request.GET) # 原来的get请求提交的参数print(request.POST) # 原来post请求提交的参数源码片段分析 源码解析之 __init__从上面区分原生request和新的request中可以知道老的request对象其实就是在新的内部request._request中我们先看__init__它是一个初始化方法类实例化得到对象时会执行它然后会往对象中放数据def __init__(self, request, parsersNone, authenticatorsNone,negotiatorNone, parser_contextNone):传入的request是老的django原生的request放到self._requestself是新的request类的对象这里它把传入过来的原request放到这个self._request中这里的self已经不是视图类了因为这个Request类没有继承任何一个类它就是它自己所以这个self是Requestself._request requestself._data Emptyself._files Empty.....在类内部以 __开头 __结尾的方法 在某种情况下会自动调用他们称之为魔法方法。具体有那些可以自行搜索因为所有的类都继承了Object类所以也可以在Object类中看看但是不全里面 源码解析之__getattr__类中有个魔法方法__getattr__对象.属性属性不存在会触发它的执行def __getattr__(self, attr): 如果取的属性不存在会去原生的Django的request对象中取出来try:通过反射因为这里是self._request所以去Django的request取能取到就返回娶不到就执行except代码如果还取不到则报错return getattr(self._request, attr)except AttributeError:return self.__getattribute__(attr)以后用的所有属性或方法直接用就可以了(通过反射去原来的request中取) 以后新的request中多了一个属性data它会把前端post/put提交的请求体中的数据都放在request.data中无论何种编码格式它都是字典 data是一个方法被property装饰了变成了数据属性用-以后body中提交的数据都从这里取(request.POST)-urlencodedform-data提交的数据在request.POST中-json格式提交的数据在request.POST中是没有的它在request.body中-现在无论那种格式都可以直接从request.data中取request.query_paramsget请求提交的参数以后从这里取request.FILES取文件就还是从这个里面取和之前一样总结 1.新的request跟之前的用法一模一样如果新的request取不到它使用__getattr__魔法方法去原生request中取。当然原生的也可以直接在新的request中拿到request._request2.新的request中多了data属性request.data客户端提交的请求体中的数据无论是什么编码都在request.data中3.其他的使用和原生的request一模一样request.query_params就是原来的request._request.GET上传的文件从request.FILES1.原生Django提交数据(post)只能处理urlencoded和form-data编码从request.POST中取2.原生Django提交数据(put)处理不了需要我们从request.body中取出来进行处理分不同编码格式urlencoded------》例namelqzage19---》使用字符串切割的方式.splitjson-----{xxx:xx,yyy:yy}---需要自己进行json.loads反序列化3.原生Django不能处理json提交的数据(post/put)需要自己做反序列化json-----{xxx:xx,yyy:yy}---需要自己进行json.loads反序列化4.新的request解决了所有问题request.data二、DRF之序列化组件 序列化类(组件)可以做的事情1.序列化QuerySet对象单个对象做序列化给前端2.反序列化数据校验前端传入数据后校验数据是否合法3.反序列化数据保存前端传入数据存到数据库中序列化介绍
在写接口时需要序列化和反序列化而且反序列化的过程中要做数据校验drf直接提供了固定的写法只需要按照固定写法只需要按照固定写法使用就能完成上面的三个需求。提供了两个类Serializer、ModelSerializer编写自定义的类只需要继承drf提供的序列化类就可以使用其中的某些方法也能完成上面的三个需求 序列化类的作用做序列化、反序列化、反序列化校验 序列化步骤 1.写一个py文件叫serializer.py(命名随意)2.写一个序列化类继承serializers.Serializer3.在类中编写需要序列化的字段例nameserializers.CharField()4.在视图类中使用导入models文件中的类books然后实例化得到对象对查出来的query对象们对单个对象序列化并传入instancebooks参数如果query是复数一定要串manyTrue如果query是单个对象就无需传入many5.序列化类对象ser.data----字典或列表-----通过Response将json格式字符串返回给前端序列化组件的基本使用
1.创建一个py文件 ----》serializer.pyfrom rest_framework import serializersclass BookSerializer(serializers.Serializer):name serializers.CharField(max_length18, min_length2, requiredTrue)price serializers.IntegerField(requiredTrue)2.view.py文件中from app01 import modelsfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom .serializer import BookSerializerclass BookView(APIView):def get(self, request):book_list models.Book.objects.all()ser BookSerializer(instancebook_list, manyTrue) # 序列化多条需要manyTruereturn Response({code: 100, msg: 查询成功, results: ser.data}) # 无论是列表还是字典都可以序列化class BookDetailView(APIView):def get(self, request, pk):book_obj models.Book.objects.filter(pkpk).first()ser BookSerializer(instancebook_obj)if ser.is_valid():return Response({code: 100, msg: 查询一条成功, results: ser})else:return Response(ser.errors)3.urls.py文件中urlpatterns [path(books/, views.BookView.as_view()),path(books/int:pk, views.BookDetailView.as_view()),]反序列化基本使用 反序列化过程新增、修改 新增1. 前端传入后端的数据不论编码格式都在request.data中request.data格式是字典前端根据传入的编码格式不一样从request.data取到的字典形式也是不一样的编码格式 字典urlencoded QueryDictform-data QueryDictjson dict2. 将前端传入的数据request.data进行反序列化并完成序列化类的反序列化3. 序列化类得到对象并传入参数datarequest.data校验数据保存ser.save()---序列化类中重写create方法修改1. 拿到前端传入的数据进行反序列化查出要修改的对象---序列化类的反序列化2. 序列化类得到对象传入参数:instance要修改的对象,datarequest.data校验数据 保存ser.save() ---序列化类中重写update方法反序列化的新增
序列化类 class BookSerializer(serializers.Serializer):name serializers.CharField()price serializers.IntegerField()# 新增一条数据def create(self, validated_data):# 保存的逻辑# validated_data 校验过后的数据 {name,price,publish}# 保存到数据库book Book.objects.create(**validated_data)# 一定不要忘记返回新增的对象return book视图类 class BookView(APIView):def get(self, request): # 获取多条数据book_list models.Book.objects.all()instance表示要序列化的数据manyTrue表示序列化多条(instance是QuerySet对象)ser BookSerializer(instancebook_list, manyTrue) # 序列化多条需要manyTruereturn Response({code: 100, msg: 查询成功, results: ser.data})def post(self, request):ser BookSerializer(datarequest.data) # 从前端传递数据从request.data中取出来if ser.is_valid(): # is_valid表示校验前端传入的数据但是我们没有写校验规则# 保存需要自己写要在序列化类BookSerializer中重写create方法ser.save() # 调用ser.save自动触发自定义编辑create方法保存数据这个时候发送post请求会发生报错NotImplementedError: create() must be implemented.这个时候点击我们点击save查看源码是调用了Save会触发BaseSerializer的方法判断了 如果instance有值执行update没有值执行create 看到create没有写 所以我们得重写Createreturn Response({code: 100, msg: 添加成功, results: ser.data})else:return Response({code: 101, msg: ser.errors})反序列化的新增
序列化类 class BookSerializer(serializers.Serializer):name serializers.CharField()price serializers.IntegerField()# 修改对象def update(self, instance, validated_data):# instance 要修改的对象# validated_date 校验过后的数据instance.name validated_data.get(name)instance.price validated_data.get(price)instance.save() # orm的单个对象修改了单个对象的属性只要调用对象.save就可以修改保存到数据库return instance # 记得把修改的对象返回视图类 class BookDetailView(APIView):def get(self, request, pk): # 获取单条数据book_obj models.Book.objects.filter(pkpk).first()ser BookSerializer(instancebook_obj)return Response({code: 100, msg: 查询一条成功, results: ser.data})def put(self, request, pk):book_obj models.Book.objects.filter(pkpk).first()ser BookSerializer(instancebook_obj,datarequest.data)if ser.is_valid():ser.save() # 同新增一样需要重写update方法return Response({code: 100, msg: 修改一条成功, results: ser.data})else:return Response({code: 101, msg: ser.errors})删除单条 class BookDetailView(APIView):def delete(self,request,pk):models.Book.objects.filter(pkpk).delete()return Response({code: 100, msg: 删除一条成功})反序列化的校验
反序列化的数据校验功能类比forms组件
局部钩子全局钩子
代码实现
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Bookclass BookSerializer(serializers.Serializer):name serializers.CharField(max_length18, min_length2, requiredTrue)price serializers.IntegerField(requiredTrue)publish serializers.CharField(min_length3)# 新增一条数据def create(self, validated_data):# 保存的逻辑# validated_data 校验过后的数据 {name,price,publish}# 保存到数据库book Book.objects.create(**validated_data)# 一定不要忘记返回新增的对象return book# 修改对象def update(self, instance, validated_data):# instance 要修改的对象# validated_date 校验过后的数据instance.name validated_data.get(name)instance.price validated_data.get(price)instance.save() # orm的单个对象修改了单个对象的属性只要调用对象.save就可以修改保存到数据库return instance # 记得把修改的对象返回# 局部钩子def validate_price(self,price):if price 10 or price 999:raise ValidationError(价格不能高于999或者低于10)return price# 全局钩子def validate(self, attrs):# 校验过后的数据出版社后三位文字与书名后三位不能一样if attrs.get(publish)[-3] attrs.get(name)[-3]:raise ValidationError(出版社后三位文字不能与书名后三位一样)return attrs序列化器常用字段和字段参数
常用字段类
字段名字段构造方式CharFieldCharField(max_lengthNone, min_lengthNone, allow_blankFalse, trim_whitespaceTrue)IntegerFieldIntegerField(max_valueNone, min_valueNone)FloatFieldFloatField(max_valueNone, min_valueNone)BooleanFieldBooleanField()NullBooleanFieldNullBooleanField()FloatFieldmax_valueNone, min_valueNoneDecimalFieldDecimalField(max_digits, decimal_places, coerce_to_stringNone, max_valueNone, min_valueNone) max_digits: 最多位数 decimal_palces: 小数点位置TimeFieldTimeField(formatapi_settings.TIME_FORMAT, input_formatsNone)DateFieldDateField(formatapi_settings.DATE_FORMAT, input_formatsNone)DateTimeFieldDateTimeField(formatapi_settings.DATETIME_FORMAT, input_formatsNone)EmailFieldEmailField(max_lengthNone, min_lengthNone, allow_blankFalse)RegexFieldRegexField(regex, max_lengthNone, min_lengthNone, allow_blankFalse)SlugFieldSlugField(maxlength50, min_lengthNone, allow_blankFalse) 正则字段验证正则模式 [a-zA-Z0-9-]URLFieldURLField(max_length200, min_lengthNone, allow_blankFalse)UUIDFieldUUIDField(format’hex_verbose’) format: 1)hex_verbose如5ce0e9a5-5ffa-654b-cee0-1238041fb31a 2hex如 “5ce0e9a55ffa654bcee01238041fb31a” 3int - 如: “123456789012312313134124512351145145114” 4urn 如: urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31aIPAddressFieldIPAddressField(protocol’both’, unpack_ipv4False, **options)DurationFieldDurationField()ChoiceFieldChoiceField(choices) choices与Django的用法相同MultipleChoiceFieldMultipleChoiceField(choices)FileFieldFileField(max_lengthNone, allow_empty_fileFalse, use_urlUPLOADED_FILES_USE_URL)ImageFieldImageField(max_lengthNone, allow_empty_fileFalse, use_urlUPLOADED_FILES_USE_URL)ListFieldListField(child, min_lengthNone, max_lengthNone)DictFieldDictField(child) 在序列化器内使用这些字段则是将接收到的字段转换成某个类型的。 如id字段值为int类型我们通过idserializer.CharField()来接收那么返回到视图里面的则是字符串类型了。 常用字段参数
选项参数字段不同可使用的参数也不同
参数名称作用max_length最大长度min_lenght最小长度allow_blank是否允许为空trim_whitespace是否截断空白字符
IntegerField
参数名称作用max_value最小值min_value最大值
通用参数
参数名称说明read_only表明该字段仅用于序列化输出默认Falsewrite_only表明该字段仅用于反序列化输入默认Falserequired表明该字段在反序列化时必须输入默认Truedefault反序列化时使用的默认值allow_null表明该字段是否允许传入None默认Falsevalidators该字段使用的验证器error_messages包含错误编号与错误信息的字典label用于HTML展示API页面时显示的字段名称help_text用于HTML展示API页面时显示的字段帮助提示信息 序列化器-source的使用
提前准备好models.py中的数据 from django.db import models# 创建关联表class Book(models.Model):name models.CharField(max_length32)price models.DecimalField(max_digits5, decimal_places2)# 外键 书与出版社 -对多关联字段写在多的一方写在Bookpublishmodels.ForeignKey(toPublish,on_deletemodels.CASCADE)# 书与作者 多对多 需要建立中间表django自动生成第三张表authors models.ManyToManyField(toAuthor)class Publish(models.Model):name models.CharField(max_length32)city models.CharField(max_length32)email models.EmailField()class Author(models.Model):name models.CharField(max_length32)age models.IntegerField()source
可以定制序列化字段名防止数据被人篡盗将前端展示的字段名和后端数据的字段名设置成不同的字段名
source序列化自有字段和关联字段的区别 serializer.pyclass BookSerializer(serializers.Serializer):自有字段修改字段映射字段直接随意写序列化字段名book_price serializers.CharField(sourceprice)name serializers.CharField(sourcename)关联字段通过外键获取一对一、一对多的关联直接使用外键字段点publish serializers.CharField(max_length8,sourcepublish.name)多对多的关联source不能用实现定制序列化关联表的字段authors serializers.CharField(sourceauthors.all)代码展示 视图类class BookAPIView(APIView):def get(self,request):books Book.objects.all()ser BookSerializer(instancebooks,manyTrue)return Response(ser.data)定制序列化类from rest_framework import serializers# 序列化类class BookSerializer(serializers.Serializer):# 字段参数 都可以通过sourse定制具体的字段名# 自有字段直接写表字段名real_name serializers.CharField(max_length8,sourcename)real_price serializers.CharField(sourceprice)# 关联字段 一对多 直接通过外键点publishserializers.CharField(sourcepublish.name)# 多对多source不能用定制关联表的字段authors serializers.CharField(sourceauthors.all)1.我们序列化的是book表字段,自有字段名直接通过sourse指定的字段名--是Book表的字段名2.sourse定制目标的字段名namemax_length8...3.提高了安全性后端真实的字段名name、price序列化给前端字段名real_name、real_priceauthors: QuerySet [Author: Author object (1), Author: Author object (2)]定制字段的两种方式
定制关联字段publish/authors的显示形式
一对多显示字典{}多对多显示列表套字典[{},{},{}]
SerializerMethodField定制 返回给前端的格式 {name: 西游记,price: 66.00,publish_detail: {name: 东方出版社,city: 东方},author_list: [{name: 张三,city: 19}]},高级序列化之SerializerMethodField class BookSerializer(serializers.Serializer):name serializers.CharField()price serializers.CharField()# 定制返回格式----serializerMethodField# 只要写了这个字段类serializerMethodField必须配合get_字段名publish_detail serializers.SerializerMethodField()def get_publish_detail(self, obj):print(obj) # 当前序列化到的book对象return {name: obj.publish.name, city: obj.publish.city}author_list serializers.SerializerMethodField()def get_author_list(self,obj):l []for author in obj.authors.all():l.append({name: author.name, city: author.age})return l在表模型中定制 返回给前端格式 {name: 西游记,price: 66.00,publish_detail: {name: 东方出版社,city: 东方},author_list: [{name: 张三,age: 19}]},models.pyclass Book(models.Model):name models.CharField(max_length32)price models.DecimalField(max_digits5, decimal_places2)publish models.ForeignKey(toPublish, on_deletemodels.CASCADE)authors models.ManyToManyField(toAuthor)# 定制在模型类中的方法def publish_detail(self):return {name: self.publish.name, city: self.publish.city}def author_list(self):l []for author in self.authors.all():l.append({name: author.name, age: author.age})return lclass BookSerializer(serializers.Serializer):name serializers.CharField()price serializers.CharField()# 定制返回格式----在表模型中写方法在序列化类中做映射publish_detail serializers.DictField()author_list serializers.ListField()总结
在序列化类中继承SerializerMethodField类中编写一个get_字段名(get_publish_detail)方法该方法返回值该字段值该字段只能做序列化字段反序列化不行在表模型中使用编写get_字段名(get_publish_detail)方法该publish_detail等于方法返回的值序列化类中需要配合ListFieldDictField两个字段类型----该字段只能做序列化使用不能实现做反序列化的字段可以将上述的方法可以包装成数据属性—使用伪装property 反序列化之保存数据
这里我就使用多表关联 反序列化校验执行流程1.先执行自有字段的校验参数控制-----》最大长度、最小长度、是否为空、是否必填、最小数字2.validators[方法] ----单独给这个字段加校验规则这个用的少因为局部钩子就能实现nameserializers.CharField(validators[方法,])3.局部钩子校验规则4.全局钩子校验规则新增
views.py class BookView(APIView):def get(self, request):books models.Book.objects.all()ser BookSerializer(instancebooks, manyTrue)return Response(ser.data)def post(self,request):ser BookSerializer(datarequest.data)if ser.is_valid():ser.save() # 书写序列化类中create方法return Response(ser.data)else:return Response(ser.errors)序列化类中使用read_only和write_only分别定制序列化和反序列化的序列外键字段并重写新增接口的create方法read_only和write_only的目的是需要序列化和反序列化的类就可以使用这两种方法 read_only表明该字段仅用于序列化输出默认是False序列化过程write_only表明该字段经用于反序列化输入默认是False反序列化过程
serializer.py class BookSerializer(serializers.Serializer):公共的name serializers.CharField()price serializers.CharField()只用来做反序列化# publish serializers.IntegerField(write_onlyTrue)publish_id serializers.IntegerField(write_onlyTrue)authors serializers.ListField(write_onlyTrue)只用来做序列化publish_detail serializers.SerializerMethodField(read_onlyTrue)author_list serializers.SerializerMethodField(read_onlyTrue)def get_publish_detail(self, obj):print(obj) # 当前序列化到的book对象return {name: obj.publish.name, city: obj.publish.city}def get_author_list(self,obj):l []for author in obj.authors.all():l.append({name: author.name, city: author.age})return l新增继承Serializer类必须要重写create方法def create(self, validated_date): # validated_date是校验过后的数据authors validated_date.pop(authors)print(authors)print(------)print(validated_date)这里不能用**validated_date打散的方式因为我们写的是 publish1这种的它需要放一个对象而其实存进去是publish_id1一个数字所以无法使用如果想要使用这个**打散的方式需要把上面的publish改成publish_id然后前端发送的也改成publish_id# name validated_date.get(name)# price validated_date.get(price)# publish_id validated_date.get(publish)# book models.Book.objects.create(namename,priceprice,publish_idpublish_id)book models.Book.objects.create(**validated_date)book.authors.add(*authors)return book修改 修改跟新增不一样因为得知道修改那一条所以接口就得不一样需要获取到想要修改的一条数据 urls.py urlpatterns [path(books/int:pk, views.BookDetailView.as_view()),]views.py class BookDetailView(APIView):def put(self, request, pk):book models.Book.objects.get(idpk)ser BookSerializer(instancebook, datarequest.data)if ser.is_valid():ser.save()return Response(ser.data)else:return Response(ser.errors)serializer.py class BookSerializer(serializers.Serializer):公共的name serializers.CharField()price serializers.CharField()只用来做反序列化# publish serializers.IntegerField(write_onlyTrue)publish_id serializers.IntegerField(write_onlyTrue)authors serializers.ListField(write_onlyTrue)只用来做序列化publish_detail serializers.SerializerMethodField(read_onlyTrue)author_list serializers.SerializerMethodField(read_onlyTrue)def get_publish_detail(self, obj):print(obj) # 当前序列化到的book对象return {name: obj.publish.name, city: obj.publish.city}def get_author_list(self,obj):l []for author in obj.authors.all():l.append({name: author.name, city: author.age})return l修改,继承Serializer类必须要重写update方法def update(self, instance,validated_date):# validated_data 校验过后的数据authors validated_date.pop(authors)如果是用的publish的又想要一次性传入进去就得自己在定义一个publish_id# validated_date[publish_id] validated_date.pop(publish)for key in validated_date:setattr(instance, key, validated_date[key])instance.save()也可以直接使用set修改无需清空后再添加instance.authors.clear()instance.authors.add(*authors)# instance.authors.set(authors) # 无需打散传入了return instance反序列化之数据校验
serializer.py 这里沿用上面案例的数据添加数据校验数据校验和上面的反序列校验一样所以这里就不细说了 校验自有的字段name serializers.CharField(max_length8,error_messages{max_length:不能超过8位})局部钩子校验def validate_name(self,name):l [sb, 傻逼,fw]for i in l:if i in name:raise ValidationError(图书命名中不能有敏感词)return name局部钩子校验def validate_price(self, price):if int(price) 10 or int(price) 999:raise ValidationError(图书价格不能小于2位数或者不能大于4位数)return price全局钩子校验def validate(self,attrs):print(attrs)publish_id attrs.get(publish_id)print(publish_id)publish_obj models.Publish.objects.filter(pkpublish_id).first()print(publish_obj.name)if attrs.get(name)[-2] publish_obj.name[-2]:raise ValidationError(图书名后两位不能与出版社后两位相同)return attrsModelSerializer的使用 ModelSerializer继承了Serializer帮我们完成了很多的操作比如跟表模型强关联大部分的请求post和put等几乎不用再序列化的时候重写create和update方法了。 使用方式跟上面的Serializer的基本一样我这里就还是用上面的案例来操作 serializer.py 继承ModelSerializer类做序列化、反序列化以及校验操作
class BookModelSerializer(serializers.ModelSerializer):其他跟Serializer一样使用不过无需再重写create和update方法只用来做序列化,这些扩写的字段也需要在field中注册publish_detail serializers.SerializerMethodField(read_onlyTrue)author_list serializers.SerializerMethodField(read_onlyTrue)def get_publish_detail(self, obj):print(obj) # 当前序列化到的book对象return {name: obj.publish.name, city: obj.publish.city}def get_author_list(self, obj):l []for author in obj.authors.all():l.append({name: author.name, city: author.age})return lclass Meta:model models.Book # 这两句是会把表模型中的Book所有字段映射过来# fields __all__fields [name, price, publish, authors, publish_detail, author_list]如果使用表模型定制字段然后在fields中注册了可以直接在extra_kwargs中设置字段属性read_onlyextra_kwargs { # 给某个或某几个字段设置字段属性name: {max_length: 18, min_length: 2},price: {max_digits: 8, decimal_places: 3},publish: {write_only: True},authors: {write_only: True},# publish_detail: {read_only: True},# author_list: {read_only: True},}局部钩子def validate_name(self,name):l [sb, 傻逼,fw]for i in l:if i in name:raise ValidationError(图书命名中不能有敏感词)return namedef validate_price(self, price):if int(price) 10 or int(price) 999:raise ValidationError(图书价格不能小于2位数或者不能大于4位数)return price# 全局钩子# def validate(self,attrs):# print(attrs)# publish_id attrs.get(publish)# print(publish_id)# publish_obj models.Publish.objects.filter(pkpublish_id).first()# print(publish_obj.name)# if attrs.get(name)[-2] publish_obj.name[-2]:# raise ValidationError(图书名后两位不能与出版社后两位相同)# return attrs这里为了区分一下我就更改了接口路由 urlpatterns [path(books/, views.BookModelView.as_view()),path(books/int:pk, views.BookDetailModelView.as_view()),]views.py视图类也是为了做一下区分所以我修改了序列化类名其他跟serializer那个操作一样 继承serializer类的ModelSerializer方式class BookModelView(APIView):def get(self,request):book models.Book.objects.all()ser BookModelSerializer(instancebook,manyTrue)return Response(ser.data)def post(self,request):ser BookModelSerializer(datarequest.data)if ser.is_valid():ser.save()return Response(ser.data)else:return Response(ser.errors)class BookDetailModelView(APIView):def put(self, request, pk):book models.Book.objects.filter(pkpk).first()ser BookModelSerializer(instancebook, datarequest.data)if ser.is_valid():ser.save()return Response(ser.data)else:return Response(ser.errors)使用方法 1.定义一个类继承ModelSerializer2.类内部写内部类 Class Meta:注意区分大小写3.在内部类中指定model(需要序列化的表)4.在内部类中指定fields(要序列化的字段写__all__表示所有不包含方法也可以写一个个的字段)5.在内部类中指定extra_kwargs给字段天津爱字段参数6.在序列化类中可以重写某个字段优先使用你重写的name serializers.SerializerMethodField()def get_name(self,obj):return obj.name __fw7.以后几乎不需要重写create和update方法了(除非有需求要用到就得重写)-ModelSerializer写好了兼容性更好任意表都可以直接存总结 ModelSerializer继承自Serializer我们可以直接查询多条单条新增和修改等操作针对fields[name,email,city]里面的参数要求1.只要是序列化的字段和反序列化的字段都要在这注册 如publish_detail,publish,authors2.序列化的字段可能不是表模型的字段是自己写的方法3.序列化的字段可能是使用SerializerMethodField也要注册