21 序列化器(一)

作用

1, 反序列化: 将json(dict)数据, 转成模型类对象
①: 校验
②: 入库

2, 序列化: 将模型类对象, 转成json(dict)数据

校验

①: 校验
1, 字段类型校验
2, 字段选项校验
3, 单字段校验, 方法
4, 多字段校验, 方法
5, 自定义校验, 方法

入库

1、create

2、update

定义

定义序列化器:
1, 定义类, 继承自Serializer
2, 编写字段名称, 和模型类一样
3, 编写字段类型, 和模型类一样
4, 编写字段选项, 和模型类一样
read_only: 只读
label: 字段说明

使用序列化器

创建

1、在应用(app)中创建serialzers.py文件

序列化字段 写入serialzers.py 文件中

from rest_framework  import serializers

class BookInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='id',read_only=True)
    btitle = serializers.CharField(max_length=20,label='名称')
    bpub_dae = serializers.DateField(label='发表日期')
    bread = serializers.IntegerField(default=0,label='阅读量')
    bcomment = serializers.IntegerField(default=0,label='评论量')
    is_delete = serializers.BooleanField(default=False,label='逻辑删除')

  

使用序列化器中的序列化 :修改原来的 view.py 的文件

from django import http
import json

# 创建视图
from django.views import View

from ..models import BookInfo

from ..serializers import BookInfoSerializer




class BookInfoView(View):
    def get(self,request):
        '''获取所有书籍'''
        # 查询所有书籍
        books = BookInfo.objects.all()
        #  [, , , ]
        # 数据转换
        '''
        book_list=[]
        for book in books:
            book_dict = {
                'id':book.id,
                'btitle':book.btitle,
                'bpub_date':book.bpub_date,
                'bread':book.bread,
                'bcomment':book.bcomment,
                'is_delete':book.is_delete
            }
            book_list.append(book_dict)
        '''''
        serializers = BookInfoSerializer(instance=books,many=True)

        # 返回json格式数据  safe=False可以安全返回非字典
        return http.JsonResponse(serializers.data,safe=False)

    def post(self,request):
        dict_data=json.loads(request.body.decode())
        # 检验参数
        # 数据入库
        book = BookInfo.objects.create(**dict_data)
        #返回book是一个字典 入库后的数据

        # 返回响应
        '''
        book_dict = {
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'is_delete': book.is_delete
        }
        '''''

        serializers = BookInfoSerializer(instance=book)
        return http.JsonResponse(serializers.data,status=201)


class BookInfoDetailView(View):
    def get(self,request,id):
        # 通过id获取
        book = BookInfo.objects.get(pk=id)

        # 返回数据

        '''
        book_dict = {
            'id':book.id,
            'btitle':book.btitle,
            'bpub_date':book.bpub_date,
            'bread':book.bread,
            'bcomment':book.bcomment,
            'is_delete':book.is_delete
        }
        '''''
        serializers = BookInfoSerializer(instance=book)
        return http.JsonResponse(serializers.data,status=200)

    # 更新单个
    def put(self,request,id):
        # 获取更新结果和根据id获取该项
        book_data = json.loads(request.body.decode())
        # book = BookInfo.objects.get(id=id)
        # 校验参数(省略)
        # 更新数据
        BookInfo.objects.filter(id=id).update(**book_data)
        # 返回数据
        book = BookInfo.objects.get(id=id)
        '''
        book_dict = {
            'id': book.id,
            'btitle': book.btitle,
            'bpub_date': book.bpub_date,
            'bread': book.bread,
            'bcomment': book.bcomment,
            'is_delete': book.is_delete
        }
        '''''
        serializers = BookInfoSerializer(instance=book)
        return http.JsonResponse(serializers.data)

    # 删除单个
    def delete(self,request,id):
        book = BookInfo.objects.get(id=id)
        book.delete()
        return http.JsonResponse({'msg':'删除成功'},status=204)

  其中 many=True 是运行序列化多个对象 默认是False

在 postman中发送请求看看是否成功

如果要序列化外键呢?即英雄外键绑定书籍 我们查询书籍想要把英雄查询出来

序列化器中

class BookInfoSerializer(serializers.Serializer):
    ......
    heroinfo_set = serializers.StringRelatedField(read_only=True,many=True)
  # 或者下面 # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)

  

如果我们查询的是英雄  我们知道是哪本书籍的呢

   # hbook = serializers.PrimaryKeyRelatedField(read_only=True)
   # hbook = serializers.PrimaryKeyRelatedField(queryset=BookInfo.objects.all()) # 关联自定义的 模块__str__函数返回值 可以自定义 在书籍的模型中的__str__方法自定义 # hbook = serializers.StringRelatedField(read_only=True) # 关联整个对象 hbook = BookInfoSerializer()

  

序列化器中的反序列化

定义:json转换模型对象 ,json是接口发送的json格式给服务器转换成模型对象 ,其中接口发送的json就是写 而 模型对象转换为json就是读

json==>模型类==>写==>反序列化

模型类==>json==>读==>序列化

步骤

反序列化==>校验字段==>入库

输入 python manage.py shell

粘贴

# 模拟获取接口传入数据
book_dict = {
    'btitle':'jin瓶梅x',
    'bpub_date':'2000-1-12',
    'bread':10,
    'bcomment':'a'
}

# 导入序列化器
from book.serializers import BookInfoSerializer
# 反序列化
serializer = BookInfoSerializer(data=book_dict)
# 校验规则如果校验不通过则抛出异常
serializer.is_valid(raise_exception=True) 
#打印 反序列化结果
print(serializer.data)
BookInfoSerializer(instance=xx) 是序列化
BookInfoSerializer(data=xx)是反序列化
校验是校验什么呢?
校验传入的字段是否满足模型类中设置的要求!
例如:是否是字符串、数字、布尔类型 长度是否满足要求,只读、只写等等

那么我们也可以在设置校验规则 开头说明有五种校验规则

1 、单字段校验 -- 加入的书名必须包含 jin瓶 两个字

class BookInfoSerializer(serializers.Serializer):
  	......
    # 单字段验证 判断是否书名是否存在 jin瓶
    # 固定格式 validate_字段名()
    def validate_btitle(self,value):
        '不管return 什么都是验证成功 所以得抛出异常'
        if 'jin瓶' not in value:
            raise serializers.ValidationError('书名不包括jin瓶')
        return value

  

2、多字段校验 -- 阅读量必须大于评论量

class BookInfoSerializer(serializers.Serializer):
	.......
    # 阅读量要大于评论量 函数名是必须是这样子写
    def validate(self, attrs):
        '''
        :param attrs: 是 books 外面data的值
        :return:
        '''
        # 获取
        bread = attrs['bread'] #阅读量
        bcomment = attrs['bcomment'] #评论量
        # 比较
        if bcomment>bread:
            raise serializers.ValidationError('评论量不能大于阅读量')
        return attrs

  

3、自定义检验 -- 因为比较少用

 

 

  其中方法函数不在序列化器中

入库

book_dict = {
    'btitle':'jin瓶梅x',
    'bpub_date':'2000-1-12',
    'bread':100,
    'bcomment':20
}

# 校验规则
from booktest.serializers import BookInfoSerializer
serializer = BookInfoSerializer(data=book_dict)
serializer.is_valid(raise_exception=True)

#
serializer.save()

  save() 现在调用的是create方法但是序列化器中我们并没有写create方法 这样中运行你可以试试看会报 找不到create函数

create

 我们现在就来写一个create方法

class BookInfoSerializer(serializers.Serializer):
....

def create(self, validated_data):
'''
:param validated_data: 是检验后的数据
:return:
'''
book = BookInfo.objects.create(**validated_data)
# print(book)
return book

update

更新 传入一个对象 来替换现有的一个对象

book_dict = {
    'btitle':'jin瓶梅x',
    'bpub_date':'2000-1-12',
    'bread':100,
    'bcomment':20
}
from book.models import BookInfo

book = BookInfo.objects.get(id=1) # 校验规则 from booktest.serializers import BookInfoSerializer serializer = BookInfoSerializer(instance = book,data=book_dict) serializer.is_valid(raise_exception=True) # serializer.save()

  这时save()就会调用update函数 只要序列化器传入instance和data save()就会调用update函数

我们来写一个

class BookInfoSerializer(serializers.Serializer):
....

    def update(self, instance, validated_data):
        instance.btitle = validated_data['btitle']
        instance.bpub_date=validated_data['bpub_date']
        instance.bread = validated_data['bread']
        instance.bcomment = validated_data['bcomment']

        instance.save()
        return instance

  

 

posted @ 2021-11-04 13:12  彡心如止水彡  阅读(69)  评论(0)    收藏  举报