rest_framework序列化组件
rest_framework序列化组件
rest_framework序列化组件是干啥的?
rest_framework序列化组件就是将需要其他数据类型都转成字符串
项目有前后端分离和前后端不分离的,前后端不分离的项目可以通过模板语法直接将后端的变量,对象传给前端,前端可以直接使用,而前后端分离的项目就是后端只写逻辑不管前端,只需要提供接口就行了,并且整个后端不同的模块可以由不同的语言编写,那么他们怎么和前端交互呢?那就是字符串,字符串是所有语言通用的一个数据类型。
如何使用drf的序列化组件
1,先建表,完成表的迁移
执行 python manage.py makemigrations 和 python manage.py migrate
class Books(models.Model): name = models.CharField(max_length=32) author = models.CharField(max_length=32) xxx = models.CharField(max_length=32) ooo = models.CharField(max_length=32) publish = models.ForeignKey('Publish',null=True) def add(self): return self.name +':'+ self.author class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() # def __str__(self): # return self.name
2,新建一个序列化类,
序列化类有两种,一种继承serializers,一种继承ModelSerializer
from app01 import models
from rest_framework import serializers
class Publish_ser(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookSerializer(serializers.Serializer): id = serializers.CharField() title = serializers.CharField(source='name')#source='name'表示序列化表的name字段,title表示把name改成title来显示 author = serializers.CharField()#默认序列化author字段并且显示的也是author publish = serializers.CharField() xxx = serializers.CharField(source='add') publish_dic = serializers.SerializerMethodField() def get_publish_dic(self,obj):#obj就是当前的Books这个表对象 return {'name':obj.publish.name,'email':obj.publish.email
继承serializers的序列化类必须写需要序列化的字段,可以用source改显示的名字,
source:可以指定字段source='name' 可以跨表source=publish.name,也可以指定方法source='add'
read_only=True:反序列化时,不传,就是说这个字段不需要前端传过来,后端自己生成,比如用户创建的时间createtime
write_only=True:序列化时,不显示,write_only表示只能写,不能读。例如定义序列化器时,password字段(还有短信验证码等)通常指定write_only=True。在序列化时,即对象转为字典、JSON字符串时,字典、JSON字符不会包含这个字段。
就是说前端向后端取数据时不显示出来,比如我们登录的qq是找不到密码的显示的。
class BookModelerializer(serializers.ModelSerializer): class Meta: model = models.Books #指定表模型 fields = '__all__' # depth = 1 publish = serializers.CharField(source='publish.name') publish_dic = serializers.SerializerMethodField() def get_publish_dic(self,obj): publish_list = models.Publish.objects.all() publish_ser = Publish_ser(instance=publish_list,many=True) return publish_ser.data name = serializers.CharField(max_length=5,min_length=2,error_messages={ 'max_length':'太长了', 'min_length':'太短了', }) def validate_name(self, value): from rest_framework import exceptions if value.startswith('sb'): raise exceptions.ValidationError('铭感词会') return value
继承ModelSerializer的序列化类需要指定表模型关键字model,还要指定需要序列化的字段,关键字fields,
fields = "__all__"表示将全部的字段都序列化,显示的就是每个字段具体的值,publish显示的是数字,要想显示publish表具体的数据有两种方法,
1):可配置depth=1,显示深度为1表示会显示出其深度为1的关联表,depth推荐最大不要超过3;
2):还可以使用SerializerMethodField,如上publish_dic字段,使用它后后面必须定义一个 get_"字段名" 的函数,这个函数的返回值就会当成publish_dic的值。
如果想重写字段,在class:Meta上面或者下面写:name=serialzier.CharField(source='字段,方法,对象.字段'),这样会把原来的name字段覆盖掉,也可以写全新的字段比如publish_dic
fields = ('name','author')表示只序列化name和author字段,
在此基础上我们如果想在添加一个字段,publish = serializers.CharField(source='publish.name'),那么就必须把publish加入到fields里面fields = ('name','author','publish')不然会报错
AssertionError: The field 'publish' was declared on serializer BookModelerializer, but has not been included in the 'fields' option.
AssertionError:字段'publish_dic'在序列化程序BookModelerializer上声明,但未包含在'fields'选项中。
exclude=('name')表示除了name字段,其他字段都序列化
3,在视图中使用序列化的类
-1 实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)
-2 对象.data
-3 return Response(对象.data)
class Books(APIView): def get(self,request,*args,**kwargs): book_list = models.Books.objects.all() data = {'code': 333, 'msg': '请求成功',} # book_ser = mySer.BookSerializer(book_list,many=True) book_ser = mySer.BookModelerializer(book_list,many=True) data['books'] = book_ser.data return Response(data)#返回的字典比较美观,做了格式化 # return HttpResponse(json.dumps(data,ensure_ascii=False))#返回的字典挤到一堆,不方便看 def post(self,request,*args,**kwargs): print(request.data) response = {'code':333,'msg':'新增成功'} #提交的字典 book = request.data #传统方法创建对象保存 #新方法,通过序列化组件保存 book_ser = mySer.BookModelerializer(data=book) if book_ser.is_valid(): book_ser.save() else: response['msg'] = '新增失败' response['error'] = book_ser.errors response['data'] = book_ser.data return Response(response) class Book(APIView): def get(self,request,id,*args,**kwargs): data = {'code': 200, 'msg': '请求成功',} book_list = models.Books.objects.filter(pk=id).first() if book_list: book_ser = mySer.BookSerializer(book_list,many=False) data['books'] = book_ser.data else: data['msg'] = '请求的资源不存在' data['code'] = '111' return Response(data)
book_ser = mySer.BookModelerializer(book_list,many=True)
many:如果要序列化的对象book_list是一个queryset对象那么就要用many=Ture,如果是单个对象,那就需要many=False
序列化的两种方式
Serializers:没有指定表模型
-source:指定要序列化哪个字段,可以是字段,可以是方法
- SerializerMethodField的用法
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
ret=AuthorSerializer(instance=obj.authors.all(),many=True)
return ret.data
-ModelSerializers:指定了表模型
class Meta:
model=表模型
#要显示的字段
fields=('__all__')
fields=('id','name')
#要排除的字段
exclude=('name')
#深度控制
depth=1
-重写某个字段
在Meta外部,重写某些字段,方式同Serializers
反序列化
使用继承了Serializers序列化类的对象,反序列化
-在自己写的序列化类中重写create方法
-重写create方法,实现序列化
-在序列化类中:
def create(self, validated_data):
ret=models.Book.objects.create(**validated_data)
return ret
-在视图中:
def post(self,request):
bookser=BookSerializer(data=request.data)
if bookser.is_valid():
ret=bookser.create(bookser.validated_data)
return Response()
使用继承了ModelSerializers序列化类的对象,反序列化
-在视图中:
def post(self,request):
bookser=BookSerializer(data=request.data)
if bookser.is_valid():
ret=bookser.save()
return Response()
-反序列化的校验
-validate_字段名(self,value):
-如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
-如果校验通过直接return value
-validate(self,attrs)
-attrs所有校验通过的数据,是个字典
-如果校验失败,抛出ValidationError
-如果校验通过直接return attrs
-读一读源码
-全局和局部钩子源码部分
-在序列化的时候,传many=True和many=False,生成的对象并不是一个对象
-bookser.data
-之前执行过,直接返回
-get_attribute(instance, self.source_attrs)
-self.source_attrs 是source指定的通过 . 切分后的列表
-instance 当前循环到的book对象