序列化类Serializer的使用
serializer.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.IntegerField()
models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.IntegerField()
views.py
class Testbook(APIView):
def get(self,request,id):
print(id)
if id:
book = models.Book.objects.all().filter(pk=id).first()
res = BookSerializer(instance=book,many=False)
return Response(res.data)
else:
books = models.Book.objects.all()
res = BookSerializer(instance=books,many=True)
return Response(res.data)
urls.py
re_path(r'books/(?P<id>.*)',views.Testbook.as_view())
序列化类Serializer常用字段和字段参数
# 字段类和字段属性
### 字段类:跟models一一对应,但是比它多
# BooleanField
# NullBooleanField
# CharField
# EmailField
# RegexField
# SlugField
# URLField
# UUIDField
# IPAddressField
# IntegerField
# FloatField
# DecimalField
# DateTimeField
# DateField
# TimeField
# ChoiceField
# FileField
# ImageField
------ 以上都是models有的----下面是serializer独有的---
# ListField
# DictField
#### 字段属性--->写在字段类中的---》干啥用?反序列化校验用的!!!!
## 选项参数
# CharField
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
# IntegerField
max_value 最小值
min_value 最大值
# 通用参数:
### 重点讲
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
error_messages 包含错误编号与错误信息的字典
serializers反序列化
**序列化类**
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.Serializer):
# read_only=True 意思是只读,只用来做序列化,不用来做反序列化
# 如果不写read_only=True,这个字段必传,如果不传,数据校验不过
# 如果写了read_only=True,这个字段不传
id=serializers.IntegerField(read_only=True) # model中Auto,本质就是数字,IntegerField
name=serializers.CharField(max_length=8,min_length=3,error_messages={'max_length':'太长了'})
# price=serializers.IntegerField()
price=serializers.CharField(max_length=1000) # 写成CharField也能映射成功
def create(self, validated_data): # 代码一点没少写,甚至多了,好处解耦了,view代码少了
# validated_data就是校验过后的数据
# 高级
book=Book.objects.create(**validated_data)
# 菜鸡
# name=validated_data.get('name')
# price=validated_data.get('price')
# book = Book.objects.create(name=name,price=price)
return book # 一定要return新增的对象
def update(self, instance, validated_data):
# instance 是要修改的对象
# validated_data是校验过后数据
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.save() # 一定不要忘了保存,才存到数据库
return instance # 一定要return新增的对象
**视图类**
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer
# 图书新增:psot 图书查询所有:get
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ser=BookSerializer(instance=book_list,many=True)
return Response(ser.data)
def post(self,request):
# 反序列化---》传得是data=前端传入的数据request.data
ser=BookSerializer(data=request.data)
# 数据校验
if ser.is_valid(): # forms组件就这么做的
# 保存-->会报错----》需要在序列化类中重写create方法
ser.save()
return Response({'msg':'新增成功','code':100})
else:
print(ser.errors)
return Response({'msg': '数据没有校验通过', 'code': 101})
# 图书查询一个:get ,图书修改一个:put ,图书删除一个:delete
class BookDetailView(APIView):
def get(self,request,pk):
book = Book.objects.all().filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
def delete(self,request,pk):
Book.objects.all().filter(pk=pk).delete()
return Response({'code':100,'msg':"删除成功"})
def put(self,request,pk):
# 修改,就有book对象,拿到要修改的对象
book=Book.objects.filter(pk=pk).first()
# 使用data的数据,修改book这个对象
ser = BookSerializer(instance=book,data=request.data)
if ser.is_valid():
# 会报错,需要重写序列化类的updata方法
ser.save()
return Response({'code':100,'msg':"修改成功"})
else:
return Response({'code': 101, 'msg': "修改失败"})
总结:
如果给序列化器传了instance参数,通过校验后,会执行updata操作,
如果没传instance参数,通过校验后,会执行create操作。
# 改了put方法和post方法
# 1 在视图类中使用
# 新增
ser=BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
# 修改
ser=BookSerializer(instance=book,data=request.data)
if ser.is_valid():
ser.save()
# 2 在序列化类中,重写create和updata
def create(self, validated_data):
book=Book.objects.create(**validated_data)
return book
def update(self, instance, validated_data):
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.save() # 一定不要忘了保存,才存到数据库
return instance # 一定要return新增的对象
#### 每个字段有自己的校验规则#####
# 数据校验---》序列化类的字段,有字段属性
# 在字段上加属性---》就会按这个属性校验
name=serializers.CharField(max_length=8,min_length=3)
price=serializers.CharField(min_length=1000) # 写成CharField也能映射成功
# 拿到数据校验失败的原因
ser.errors
序列化类ModelSerializer的使用
# Serializer基类,序列化类都要继承它,写字段,重写create和updata方法
# 有没有一种简单方案,不写字段了(因为字段跟表有对应关系),不写update和create了
# 原来必须要重写update和create了的原因是---》新增不知道要增加到哪个表中去
# ModelSerializer就可以完成---》跟表有对应关系---》字段不用写了,存到哪也知道,不写update和create了
# 重点:
1 class Meta: 中model和fields意思
2 给字段类加属性 extra_kwargs
3 局部全局钩跟之前没有任何区别
4 create和update不需要写了
5 可以重写某个字段,但注意缩进
class BookSerializer(serializers.ModelSerializer):
# 要序列化的字段,没有写,但是写了model=Book,它自动把Book表中的字段映射出来,相当于
# name = serializers.CharField(max_length=32)
# price = serializers.IntegerField()
# 缩进关系搞懂
class Meta:
model = Book # 跟Book做对应
# fields='__all__' # 序列化和反序列化Book中的所有字段
fields = ['name', 'price'] # 只序列化和反序列化某几个字段
# 重点: 如果不重写字段,但是我想给字段类加属性---》使用下面的方式
# 如果不这样写,name会默认使用model的规则max_length=32
# 如果这样写了,最大长度是8 ,最小长度是3
extra_kwargs = {
'name': {'max_length': 8, 'min_length': 3},
'price': {'max_value': 88}
}
# 表示重写name这个字段,会走它的规则
# name=serializers.CharField(max_length=8,min_length=3)
# 之前教的局部钩子和全局钩子完全一样,一毛一样
# 不需要重写create和update方法了,因为ModelSerializer已经写了
补充 exclude
'''
补充 exclude
除了某些字段,其他的字段参与序列化,写了exclude不能写fields
'''
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book # 跟Book做对应
exclude = ['name'] # 除了name这个字段,其他的字段参与序列化,写了exclude不能写fields