首页 > 其他 > 详细

3、Serializer序列化类

时间:2021-09-11 15:31:31      阅读:14      评论:0      收藏:0      [点我收藏+]

一、序列化类之Serializer

我们之前已经的DRF使用案例中成功实现了序列化,通过for循环将数据库内容遍历到一个列表,然后用DRF的Response将列表返回给前端,但有个问题就是我们每次想把数据库的数据序列化返给前端,都要手动序列化,但有没有一种简洁的方式,只写一次之后就不用重复编写了,借助序列化类更快速的实现序列化。

序列化查询所有数据

首先依然还是需要在models.py里先用ORM命令创建个表

class Book(models.Model):  # 创建了Book表
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    # 记得迁移数据库,然后随便往表里录入几条数据

urls.py路由层开放路由接口

from app01 import views

urlpatterns = [
    path(‘admin/‘, admin.site.urls),
    path(‘books/‘, views.BookView.as_view()),
]

在应用下可以创建一个serializer.py文件,导入serializers模块对数据库进行序列化

from rest_framework import serializers  # 导入serializers模块


class BookSerializer(serializers.Serializer):
    # 想序列化哪个字段就写字段和对应的类
    name = serializers.CharField()  
    # 注意:这个CharField是DRF提供的数据类型,和Django的ORM不是一个类型!
    price = serializers.IntegerField()

views.py文件写逻辑,以序列化的方式显示给前端

from rest_framework.views import APIView  # 导入APIView
from app01 import models   # 导入models里的表
from rest_framework.response import Response
from app01.serializer import BookSerializer  # 导入serializer.py文件的序列化类


class BookView(APIView):
    # get请求走下列方法
    def get(self, request):
        book_list = models.Book.objects.all()  # 查到数据库所有数据
        # instance=book_list(序列化该对象) many=True(queryset多条对象必须用many=True)
        ser = BookSerializer(instance=book_list, many=True)  # 将数据传入第一个参数序列化
        return Response(ser.data)

就此,我们就利用serializers类实现了序列化,写好之后尝试启动服务,然后输入网址http://127.0.0.1:8000/books/就可以看见数据库里面Book表所有的书籍

我们还可以通过序列化类来控制序列化的字段了,在序列化类把某个字段注释掉,再去前端或者 postman里查看,该字段也没了

注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

通过主键筛选出单条数据

我们如何通过主键值拿到某一条数据呢,如下

# 首先路由利用转化器来实现,pk就是主键,通过网址的尾部books/1,如何根据主键拿到具体某一条数据
path(‘books/<int:pk>‘, views.BookDeteView.as_view()),

# 然后就是视图层
class BookDeteView(APIView):
    def get(self,request,*args,**kwargs):
        ‘‘‘
       不加first(),拿到的是QuerySet对象,就像这样<QuerySet [<Book: Book object (2)>]>,它还是相当于多个,就不能去掉many=True
        只有加了first(),拿到的数据才是真正单个的,这样 Book object (2)
        ‘‘‘
        book = models.Book.objects.all().filter(pk=kwargs[‘pk‘]).first()
        ser = BookSerializer(instance=book)  # 单条数据就不需要写many=True了
        return Response(ser.data)

二、序列化类常用字段

# 重点的:
‘‘‘
CharField		字符
IntegerField	数字
DecimalField
DateTimeField
DateField

ListField
DictField
‘‘‘

# 其他还有很多但的忽略

三、序列化类常用字段参数

# 通用的(所有字段都可用)
read_only	表明该字段仅用于序列化输出,默认False(重点)
write_only	表明该字段仅用于反序列化输入,默认False(重点)
required	表明该字段在反序列化时必须输入,默认True(了解)
default	    反序列化时使用的默认值(了解)
allow_null	表明该字段是否允许传入None,默认False(了解)
validators	该字段使用的验证器(写函数的列表,使用这些函数校验该字段)(了解)
error_messages	包含错误编号与错误信息的字典


# 其他的
# CharField
max_length	最大长度
min_lenght	最小长度
allow_blank	是否允许为空
trim_whitespace	是否截断空白字符

# IntegerField
max_value	最小值
min_value	最大值

四、反序列化

class BookView(APIView):
    def get(self, request):  # get请求查询数据
        book_list = models.Book.objects.all()
        ser = BookSerializer(instance=book_list, many=True)
        return Response(ser.data)

    def post(self, request):  # post请求增加数据
        # 反序列化,通过前端操作,实现数据库的增删改
        ser = BookSerializer(data=request.data)
        if ser.is_valid():  # 校验字段是否合法
            ser.save()  # 如果是新增,就新增了
            return Response({‘code‘: 100, ‘msg‘: ‘新增成功‘, ‘data‘: ser.data})
        else:
            return Response({‘code‘: 500, ‘msg‘: ser.errors})
        
        
class BookDeteView(APIView):
    def get(self, request, *args, **kwargs):  # 通过主键拿单条数据
        book = models.Book.objects.all().filter(pk=kwargs[‘pk‘]).first()
        ser = BookSerializer(instance=book)  # 单条数据就不需要写many=True了
        return Response(ser.data)

    def put(self, request, pk):  # put请求修改数据
        book = models.Book.objects.all().filter(pk=pk).first()
        # 修改数据需要进行校验,所以一定要拿到put提交的数据
        ser = BookSerializer(instance=book, data=request.data)
        # 然后进行校验,判断数据是否合法
        if ser.is_valid():
            ser.save()
            # 返回的数据符合Restful规范形式
            return Response({‘code‘: 100, ‘msg‘: ‘修改成功‘, ‘data‘: ser.data})
        else:
            return Response({‘code‘: 500, ‘msg‘: ser.errors})

    def delete(self, request, pk):  # delete请求删除数据
        res = models.Book.objects.filter(pk=pk).delete()
        if res:
            return Response({‘code‘: 100, ‘msg‘: ‘删除成功‘})
        else:
            return Response({‘code‘: 500, ‘msg‘: ‘数据不存在‘})

需要重写create和update

增加数据、更新数据都属于反序列化的操作,需要在Serializer序列化类中 重写create和update,否则会报错

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()

    def create(self, validated_data):
        book = models.Book.objects.create(**validated_data)
        return book

    def update(self, instance, validated_data):
        instance.name = validated_data.get(‘name‘, instance.name)
        instance.price = validated_data.get(‘price‘, instance.price)
        instance.save()
        return instance

五、SerializerMethodField的使用

上面都是拿一张图书表举例的,但假如我们现在又有一张出版社表,然后图书表里增加一个出版社字段,和出版社表做外键关联,那么我们如果还按照之前的方法序列化字段,那出版社的外键字段是序列化不了给用户看的。我们需要做的是找到图书表 的出版社字段关联 的 出版社表,然后把出版社表里的出版社名字序列化给前端。

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()
    price = serializers.IntegerField()
    # publish = serializers.CharField()  # 显示的是一个外键,用户看不懂!

    ‘‘‘显示出版社的详情的方案‘‘‘
    # 方式一(在序列化类中写)
    publish_name = serializers.SerializerMethodField(read_only=True)  # 只能用来做序列化
    def get_publish_name(self,obj):
        # obj 就是当前要序列化的book对象
    	# return obj.publish.name  # 显示出版的名字
        return {‘name‘:obj.publish.name,‘addr‘:obj.publish.addr}  # 显示出版社的详情

##################################################################################
    
    # 方式二(在模型类中写方法,方法返回什么,这个字段就是什么)(在表模型中写用的多)
    # 在models.py的表中写一个方法
    def publish_detail(self):
        return {‘name‘:self.publish.name}
    # 然后去序列化类里写
    publish_detail=serializers.DictField()

    # 方式三(了解类型)
    publish_detail = serializers.CharField(source=‘publish.name‘)

3、Serializer序列化类

原文:https://www.cnblogs.com/poco/p/15251259.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!