1-3.序列化组件
目录
1 序列化器-Serializer
# 序列化器的作用
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
2 序列化器的序列化和反序列化
2.1 基本使用
表模型 models.py
from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField(default='0')
publish = models.CharField(max_length=32)
路由urls.py
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>', views.BookDetailView.as_view()),
]
视图层views.py
# 针对于某个表模型,总共5个接口
# 获取所有 get
# 获取单个 get
# 删除单个 delete
# 修改单个 update
# 新增单个 post
# 以后你写的所有接口(跟数据库相关),都是这个5个或这5个的变形
from rest_framework.views import APIView
from app01.models import Book # 绝对导入
# from .models import Book # 相对导入,用了相对导入,当前py文件,不能以脚本形式运行
from .serializer import BookSerializer #导入序列化器
from rest_framework.response import Response
####################################################################################
class BookView(APIView):
################### 查询所有图书###################
def get(self, request, *args, **kwargs):
books = Book.objects.all() # 查询出所有图书
book_ser = BookSerializer(instance=books, many=True) # 传入要序列化的数据
# instance=None, 要序列化的数据
# data=empty ,要反序列化的数据(目前data先不用)
# many=True 如果序列化多条,一定要写many=True
return Response(book_ser.data) # book_ser.data就是序列化后的数据
################### 新增图书 ###################
def post(self, request, *args, **kwargs):
# 前端传入的数据,在request.data中,是个字典
# 如果不使用序列化类,如何保存
# book=Book(title=request.data.get('title'))
# book.save()
# 使用序列化类做保存
ser = BookSerializer(data=request.data)
if ser.is_valid(): # 数据校验:如果是True,表示校验通过,直接保存
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写create个方法
return Response(ser.data) # 又做了一次序列化,返回给了前端
else:
return Response(ser.errors)
####################################################################################
class BookDetailView(APIView):
################### 查询某本图书###################
def get(self, request, pk):
books = Book.objects.all().filter(pk=pk).first()
ser = BookSerializer(instance=books) # 传入要序列化的数据
return Response(data=ser.data)
################### 删除某本图书###################
def delete(self, request, pk):
# 跟序列化类没有关系
Book.objects.all().filter(pk=pk).delete()
return Response()
################### 修改某本图书###################
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid(): # 数据校验:如果是True,表示校验通过,直接保存
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写update方法
return Response(ser.data) # 又做了一次序列化,返回给了前端
序列化器serializer.py
# 写序列化类
from rest_framework import serializers
from .models import Book
from rest_framework.exceptions import ValidationError
class BookSerializer(serializers.Serializer): # 一定要继承一个序列化的基类
# 写字段,你想序列化哪个字段,就写哪个
title = serializers.CharField(max_length=8, min_length=3)
price = serializers.IntegerField()
publish = serializers.CharField()
# 重写create,使它能够支持新增保存 (派生)
def create(self, validated_data): # validated_data校验过后的数据
book = Book.objects.create(**validated_data)
return book # 一定不要忘了return 对象,否则在视图类中用ser.data 就报错了
# 重写 update 支持修改
def update(self, instance, validated_data):
instance.title = validated_data.get('title')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save()
return instance
#局部钩子
# validate_字段名 先走字段自己的,再走局部钩子
def validate_title(self, item):
print(item)
# 校验字段,不能以sb开头
if item.startswith('sb'):
raise ValidationError('不能以sb开头')
return item
# 全局钩子
def validate(self, attrs):
# 校验失败,抛异常
if attrs.get('title') == attrs.get('publish'):
raise ValidationError('标题和出版社不能一样')
return attrs
常用字段参数
#参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值
#通用参数:(针对所有字段)
参数名称 说明
#非常重要
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
3.模型类序列化器ModelSerializer
# 反序列化,正常情况不需要重写 create和update
# 序列化:跟表模型有对应关系,不需要一个个字段都写了
# class BookModelSerializer(serializers.ModelSerializer):
# # 跟某个表模型建立关系
# class Meta:
# model = Book # 跟哪个表建立关系
# fields = ['title','price','id','publish'] # 要序列化哪些字段
# # fields = '__all__' # 所有字段都序列化
#
#
# # 了解
# # exclude=['title'] # 除了某个字段外
# # depth=1 # 表关联
#
#
#
# #重点
#
# # read_only 只读,只序列化
#
# # write_only 只写,只做反序列化,这个字段不做序列化
#
# # 重写某个字段
# title=serializers.CharField(max_length=8,min_length=3)
#
# # 局部和全局钩子跟之前一模一样
#
# def validate_price(self, price):
# if not price>100:
# raise ValidationError('价格必须大于100')
#
# return price
class BookModelSerializer(serializers.ModelSerializer):
# 跟某个表模型建立关系
class Meta:
model = Book # 跟哪个表建立关系
fields = ['title', 'price', 'id', 'publish'] # 要序列化哪些字段
# 重点
# 额外给某些字段传参数
# extra_kwargs = {
# 'title': {'max_length': 8, 'min_length': 3},
# 'price': {'min_value': 100}
# }
# read_only 只读,只序列化
# write_only 只写,只做反序列化,这个字段不做序列化
extra_kwargs = {
'title': {'read_only': True},
# 'price': {'write_only': True}
}
4.多表关联的序列化和反序列化
# depth=1 # 深度查一层,官方建议不大于10,正常不超过3,不建议用
# 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
# 方法二:在序列化类中写
# 方式三:通过子序列化
方式一:在表模型中写方法,在序列化类的fields声明一下就可以
# 方式一:在表模型中写方法,在序列化类的fields声明一下就可以
############################################
models.py
from django.db import models
# Create your models here.
class Publish(models.Model):
name=models.CharField(max_length=8)
add=models.CharField(max_length=8)
class Book(models.Model):
title=models.CharField(max_length=8)
price=models.IntegerField()
publish=models.ForeignKey(to=Publish,on_delete=models.SET_NULL,null=True)
def publish_detail(self):
return {'name':self.publish.name,'add':self.publish.add}
############################################
#序列化器中
serializer.py
from rest_framework import serializers
from .models import Book,Publish
class PublishModelSerializer(serializers.ModelSerializer):
class Meta:
model=Publish
fields=['name','add']
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=Book
fields=['id','title','price','publish','publish_detail']
extra_kwargs={'publish': {'write_only': True},
'publish_detail': {'read_only': True}
}
############################################
方法二:在序列化类中写
#序列化器中
serializer.py
from rest_framework import serializers
from .models import Book,Publish
class PublishModelSerializer(serializers.ModelSerializer):
class Meta:
model=Publish
fields=['name','add']
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=Book
fields=['id','title','price','publish','publish_detail']
extra_kwargs={'publish': {'write_only': True},
}
publish_detail = serializers.SerializerMethodField(read_only=True) # 这个字段需要配合一个方法,方法必须叫get_字段名,方法返回什么,publish_detail就是什么
def get_publish_detail(self, obj):
# obj就是当前序列化到的对象,就是book对象
return {'name': obj.publish.name, 'address': obj.publish.address}
############################################
方式三:通过子序列化
#序列化器中
serializer.py
from rest_framework import serializers
from .models import Book,Publish
class PublishModelSerializer(serializers.ModelSerializer):
class Meta:
model=Publish
fields=['name','add']
class BookModelSerializer(serializers.ModelSerializer):
publish = PublishSerializer()
authors = AuthorSerializer(many=True) # 多条,一定要加一个 many=True
class Meta:
model=Book
fields=['id','title','price','publish']
extra_kwargs={'publish': {'write_only': True},
}
############################################