一、关于序列化与反序列化前端
web有两种应用模式,一种是先后端不分离,一种是先后端分离,当先后端分离的时候,后端只须要向前端传输数据便可,不须要进行其余的操做;
现阶段主流的数据格式为json格式,因此在restframework在先后端传输数据时,也主要是json数据,过程当中就要须要把其余数据转换成json数据, 好比数据库查询全部数据时,是queryset对象,那就要把这对象处理成json数据返回前端。
序列化与反序列化git
增:效验请求数据 > 执行反序列化过程 > 保存数据库 > 将保存的对象序列化并返回 删:判断要删除的数据是否存在 > 执行数据库删除 改:判断要修改的数据是否存在 > 效验请求的参数 > 执行反序列化过程 > 保存数据库 > 将保存的对象序列化并返回 查:查询数据库 > 将数据序列化并返回 rest-framework的序列化组件: 提供了定义序列化器Serializer的方法,能够快速根据Django ORM 或者其余库自动序列化/反序列化;
二、Serializers序列化与反序列化web
序列化数据库
-使用drf的序列化组件 -1 新建一个序列化类继承Serializer -2 在序列化类中写要序列化的字段 -在视图中使用序列化的类 -1 实例化序列化的类产生对象,在产生对象的时候,传入须要序列化的对象(queryset) -2 对象.data -3 return Response(对象.data) -高级用法: -source:能够指定字段(name publish.name),能够指定方法, -SerializerMethodField搭配方法使用(get_字段名字) publish_detail=serializers.SerializerMethodField(read_only=True) def get_publish_detail(self,obj): return {'name':obj.publish.name,'city':obj.publish.city} -read_only:反序列化时,不传 -write_only:序列化时,不显示
案例:
settings.pydjango
INSTALLED_APPS = [ ... 'rest_framework', ]
models.py中建表json
from django.db import models # Create your models here. class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE) authors=models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name
执行数据库迁移命令;后端
在app下新建一个序列化类并继承Serializer :app
app01serializer.py前后端分离
from rest_framework import serializers # 序列化Author的类 class AuthorSerializer(serializers.Serializer): name = serializers.CharField() age = serializers.CharField() # 序列化Book的类 class BookSerializer(serializers.Serializer): # 指定source='name',表示序列化模型表中的name字段,重名命为name5,能够避免直接暴露数据库字段 # 模型表中的字段和source指定的字段不能重名 # name = serializers.CharField() name5 = serializers.CharField(source='name') # write_only 序列化的时候,该字段不显示 # read_only 反序列化的时候,该字段不传 # price = serializers.CharField() price = serializers.CharField(write_only=True) # 若是要取出版社的city--> source='publish.city' publish = serializers.CharField(source='publish.city') # source不只能够指定一个字段,还能够指定一个方法 # 在modles.py的Book表中写了一个test方法,并返回xxx xxx = serializers.CharField(source='test') # 好比要序列化出版社的详情; SerializerMethodField对应着一个方法,方法返回什么内容,publish_detail就是什么内容 publish_detail = serializers.SerializerMethodField() # SerializerMethodField对应的方法,固定写法:get_字段名 # 由于这个类是序列化Book的,参数obj就是Book对象,而后用Book对象去拿出版社的详情 def get_publish_detail(self, obj): print(type(obj)) return {'name':obj.publish.name, 'city':obj.publish.city} # 好比要返回全部的做者信息 authors = serializers.SerializerMethodField() def get_authors(self, obj): # return [{'name': author.name, 'age': author.age} for author in obj.authors.all()] # 上面这种return的方式是用的列表推导式,当有变化时就要不断修改这个推导式, # 咱们也能够再添加一个序列化的类,当有变化时修改类就好了 # 此时在上面添加了一个序列化Author的类,在这里使用它 authorser = AuthorSerializer(obj.authors.all(), many=True) return authorser.data
在视图中使用序列化的类 :post
views.py
from app01 import models from rest_framework.views import APIView from rest_framework.serializers import Serializer
# Response本质也会是继承了Httpresponse,可是功能更强大了 from rest_framework.response import Response # 导入新建的序列化类 from app01.app01serializer import BookSerializer # Create your views here. class Books(APIView): def get(self, request): response = {"code":100, "msg":"查询成功"} books = models.Book.objects.all() # 若是序列化多条,要写many=True(序列化多条时,实际上是序列化的queryset对象 ) # 若是序列化一条,many=True能够不写(序列化一条时,就不是queryset了) bookser = BookSerializer(books, many=True) response['data'] = bookser.data print(type(bookser.data)) return Response(response)
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/', views.Books.as_view()), ]
反序列化
-使用继承了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()
在app01serializer.py的序列化Book的类中,重写create方法:
# 序列化Book的类 class BookSerializer(serializers.Serializer): ……
…… # 重写create方法 def create(self, validated_data): ret = models.Book.objects.create(**validated_data) return ret
views.py
from app01 import models from rest_framework.views import APIView from rest_framework.serializers import Serializer from rest_framework.response import Response # 导入新建的序列化类 from app01.app01serializer import BookSerializer # Create your views here. class Books(APIView): def get(self, request): response = {"code":100, "msg":"查询成功"} books = models.Book.objects.all() # 若是序列化多条,要写many=True(序列化多条时,实际上是序列化的queryset对象 ) # 若是序列化一条,many=True能够不写(序列化一条时,就不是queryset了) bookser = BookSerializer(books, many=True) response['data'] = bookser.data print(type(bookser.data)) return Response(response) def post(self, request): # 实例化产生一个序列化类的对象,data是要反序列化的字典 bookser = BookSerializer(data=request.data) if bookser.is_valid(): ret = bookser.create(bookser.validated_data) return Response()
三、ModelSerializers序列化与反序列化
序列化
app01serializer.py
from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: # 指定表模型 model = models.Book # fields表示要序列化哪几个字段 # fields=('nid','name') # exclude表示不序列化哪些字段,不能跟fields同时使用 # exclude=['name',] # __all__表示序列化全部字段 fields = ('__all__') # 深度是1,表示能够跨的表数量,官方建议不要超过10,我的建议不要超过3 # 会拿到与此表深度关系为1的表中的全部数据,且不能定制化,与下面的方式各有不一样的使用场景 depth=1 # 好比要序列化全部做者的详情信息(和Serializer中相同),这种方法能够定制化(代码在Meta类外面) # authors = serializers.SerializerMethodField() # def get_authors(self,obj): # ret = AuthorSerializer(instance=obj.authors.all(), many=True) # return ret.data
反序列化
#使用继承了ModelSerializers序列化类的对象,反序列化 #在视图中: def post(self,request): bookser=BookSerializer(data=request.data) if bookser.is_valid(): ret=bookser.save() return Response()
四、反序列化的校验
app01serializer.py
# 局部校验 def validate_name(self,value): # value就是传过来的值,如:name:wei 这里的wei就是value print(value) raise exceptions.ValidationError('不能以sb开头') # if value.startswith('sb'): # raise ValidationError('不能以sb开头') # return value #全局校验 # 若是用了fields=('__all__')的方式,这里的attrs可能会找不到具体的字段 def validate(self,attrs): # attrs是校验经过的数据,是一个字典 print(attrs) # if attrs.get('price')!=attrs.get('xx'): # raise exceptions.ValidationError('name和price相等,不正常') return attrs
views.py
class Books(APIView): def get(self,request): ... def post(self,request): #实例化产生一个序列化类的对象,data是要反序列化的字典 bookser=BookSerializer(data=request.data) # bookser.data # raise_exception=True把校验的错误数据抛到前端,先后端分离项目用不到 if bookser.is_valid(raise_exception=True): #清洗经过的数据 bookser.save() else: # 抛出校验错误的信息 print(bookser.errors['name'][0]) return Response()