Serializer序列化组件使用
在models.py中定义字段(和form组件类似)
class Book(models.Model):#全部用CharField字段也可以
id = models.AutoField(primary_key=True)#可写可不写,不写创建表时候自动生成
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)#max_digits数字最大不超过8位,其中小数部分不超过2位
author = models.CharField(max_length=32)
publish = models.CharField(max_length=32)
新建一个序列化py文件
# from rest_framework.serializers import Serializer
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from app01.models import Book
#校验作者名称不能以‘sb’开头或者结尾
#check_字段名
def check_author(data): #这个函数可以写在其他的py文件中,只要能导过来
if data.startswith('sb') or data.endswith('sb'):
raise ValidationError('作者名字不能以“sb”开头或者结尾') #抛出错误信息
else:
return data
class BookSerializer(serializers.Serializer):
id = serializers.CharField(read_only=True) #数据校验顺序是先校验id字段,是否有验证规则,(局部钩子或者全局钩子),校验完id字段后就校验name字段,校验顺序和id一样
name = serializers.CharField(max_length=8,min_length=4)
price = serializers.CharField(write_only=True) #只读,序列化时候看不到该字段
author = serializers.CharField(validators=[check_author]) #列表形式,校验作者名是否合法(可以写多个,也就是有多种校验方法)
publish = serializers.CharField()
def validate_price(self,data): #validate_字段名(固定写法) 局部钩子(和form组件的钩子函数类似)
print(data) #这个data就是price,为str类型
if float(data)>10:
return data
else:
raise ValidationError('价格太低了')
def validate(self, data): #全局钩子
print(data)
author = data.get('author')
publish = data.get('publish')
if author == publish:
raise ValidationError('作者和出版社一致了')
else:
return data
"""
# form组件的钩子函数
# 局部钩子:当你需要给单个字段增加校验规则的时候使用(校验用户名是否存在)
def clean_username(self):
username = self.cleaned_data.get(
'username')
# 去数据库校验
is_exist = models.UserInfo.objects.filter(
username=username)
if is_exist:
self.add_error('username', '用户已存在!')
return username
# 全局钩子:当需要给多个字段增加校验规则的时候使用(校验两次密码是否一致)
def clean(self):
password = self.cleaned_data.get(
'password')
confirm_password = self.cleaned_data.get(
'confirm_password')
if not password == confirm_password:
self.add_error('confirm_password',
'两次密码不一致')
return self.cleaned_data
"""
def create(self, validated_data): #重写create方法
instance = Book.objects.create(**validated_data)
return instance
def update(self, instance, validated_data):
#instance:创建序列化器时传入的实例对象,这里是book
#validated_data:校验之后的数据
#获取字段名
# id = validated_data.get('id')
name = validated_data.get('name')
price = validated_data.get('price')
author = validated_data.get('author')
publish = validated_data.get('publish')
#更新instance
# instance.id = id
instance.name = name
instance.price = price
instance.author = author
instance.publish = publish
instance.save()
#返回instance
return instance
class BookModelSerializer(serializers.ModelSerializer):
#想在ModelSerializer中写局部或者全局钩子,和在Serializer中书写的一模一样
class Meta:
model = Book
fields = '__all__'
# fields = ('name','price') #序列化name,price
# exclude = ('name',) #除了姓名没有序列化
extra_kwargs = {
'price':{'write_only':True}, #只读,运行看不到price字段
}
在views.py中
from django.shortcuts import render
# Create your views here.
from rest_framework.views import APIView
from app01.models import Book
from app01.serialize import BookSerializer
from rest_framework.response import Response
from app01.serialize import BookModelSerializer
class BookView(APIView):#下面的class都继承(APIView)
def get(self,request,pk):#restful根据请求方法的不同执行不同的操作
book = Book.objects.filter(id=pk).first()
book_serialize = BookSerializer(book) #序列化一条,其中book为序列化的对象
return Response(book_serialize.data)
def put(self,request,pk):#更新数据
back_dic = {'code':1000,'msg':''}
book = Book.objects.filter(id=pk).first()
boo_ser = BookSerializer(instance=book,data=request.data)#如果根据位置传参时候不要混乱位置
if boo_ser.is_valid():#校验数据
#保存修改,要调用序列化对象
boo_ser.save() #需要重写update方法(传了instance和data就触发update方法的执行)
back_dic['msg'] = '数据校验成功'
back_dic['data'] = boo_ser.data
else:
back_dic['code'] = 1001
back_dic['msg'] = '数据校验失败'
back_dic['data'] = boo_ser.errors
return Response(back_dic)#定义Response对象返回字典
def delete(self,request,pk): #删除
Book.objects.filter(pk=pk).delete()
return Response({'code':1000,'msg':'删除成功'})
#反序列化
class BooksView(APIView):
def get(self,request):
back_dic = {'code': 1000, 'msg': '数据反序列化成功'}
books = Book.objects.all()
books_serialize = BookSerializer(books,many=True)
#many=True能够序列化多条数据的原因--》__new__是在__init__之前执行的,造出一个空对象
back_dic['data'] = books_serialize.data
return Response(back_dic)
def put(self,request):
back_dic = {'code':1000,'msg':''}
book_ser = BookSerializer(data=request.data)
#只传了data,序列化对象.sava()方法,就触发序列化create方法的执行
if book_ser.is_valid():
book_ser.save()
back_dic['msg'] = '数据校验成功'
back_dic['data'] = book_ser.data
else:
back_dic['code'] = 1001
back_dic['msg'] = '数据校验失败'
back_dic['data'] = book_ser.data
return Response(back_dic)
#ModelSerializer
class BooksView2(APIView):
def get(self,request):
back_dic = {'code': 1000, 'msg': '数据反序列化成功'}
books = Book.objects.all()
book = Book.objects.all().first()
books_serialize = BookModelSerializer(books,many=True)
book_serialize = BookModelSerializer(book)
print(type(books_serialize))
print(type(book_serialize))
back_dic['data'] = books_serialize.data
return Response(back_dic)
urls.py
# re_path('^books/(?P<pk>\d+)',views.BookView.as_view()),#删除数据和查询一条数据的路由
# path('books/',views.BooksView.as_view()),
# path('books2/',views.BooksView2.as_view()),