DRF 序列化组件

摘要:
Serializers序列化组件Django的序列化方法classBooksView(View):defget(self,request):book_list=Book.objects.values("id","title","chapter","pub_time","publisher")book_list=list(book_list)#如果我们需要取外键关联的字段信息需要循环获取外键再去数据
Serializers 序列化组件

Django的序列化方法

DRF 序列化组件第1张DRF 序列化组件第2张
classBooksView(View):
    defget(self, request):
        book_list = Book.objects.values("id", "title", "chapter", "pub_time", "publisher")
        book_list =list(book_list)
        #如果我们需要取外键关联的字段信息 需要循环获取外键 再去数据库查然后拼接成我们想要的
        ret =[]
        for book inbook_list:
            pub_dict ={}
            pub_obj = Publish.objects.filter(pk=book["publisher"]).first()
            pub_dict["id"] =pub_obj.pk
            pub_dict["title"] =pub_obj.title
            book["publisher"] =pub_dict
            ret.append(book)
        ret = json.dumps(book_list, ensure_ascii=False, cls=MyJson)
        returnHttpResponse(ret)


#json.JSONEncoder.default()#解决json不能序列化时间字段的问题
classMyJson(json.JSONEncoder):
    defdefault(self, field):
        ifisinstance(field, datetime.datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elifisinstance(field, datetime.date):
            return field.strftime('%Y-%m-%d')
        else:
            return json.JSONEncoder.default(self, field)
.values 序列化结果
DRF 序列化组件第3张DRF 序列化组件第4张
from django.core importserializers


#能够得到我们要的效果 结构有点复杂
classBooksView(View):
    defget(self, request):
        book_list =Book.objects.all()
        ret = serializers.serialize("json", book_list)
        return HttpResponse(ret)
django serializers

DRF序列化的方法

首先,我们要用DRF的序列化,就要遵循人家框架的一些标准,

-- Django我们CBV继承类是View,现在DRF我们要用APIView

-- Django中返回的时候我们用HTTPResponse,JsonResponse,render ,DRF我们用Response

为什么这么用~我们之后会详细讲~~我们继续来看序列化~~

序列化

DRF 序列化组件第5张DRF 序列化组件第6张
classBookSerializer(serializers.Serializer):
    id =serializers.IntegerField()
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Linux"), (2, "Django"), (3, "Python"))
    chapter = serializers.ChoiceField(choices=CHOICES, source="get_chapter_display")
    pub_time = serializers.DateField()
第一步 声明序列化类
DRF 序列化组件第7张DRF 序列化组件第8张
from rest_framework.views importAPIView
from rest_framework.response importResponse

classBookView(APIView):
    defget(self, request):
        book_list =Book.objects.all()
        ret = BookSerializer(book_list, many=True)
        return Response(ret.data)
第二部 序列化对象

外键关系的序列化

DRF 序列化组件第9张DRF 序列化组件第10张
#by gaoxin
from rest_framework importserializers
from .models importBook


classPublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)


classUserSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(max_length=32)
    age =serializers.IntegerField()


classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Linux"), (2, "Django"), (3, "Python"))
    chapter = serializers.ChoiceField(choices=CHOICES, source="get_chapter_display", read_only=True)
    pub_time =serializers.DateField()

    publisher = PublisherSerializer(read_only=True)
    user = UserSerializer(many=True, read_only=True)
外键关系的序列化

反序列化

当前端给我们发post的请求的时候~前端给我们传过来的数据~我们要进行一些校验然后保存到数据库~

这些校验以及保存工作,DRF的Serializer也给我们提供了一些方法了~~

首先~我们要写反序列化用的一些字段~有些字段要跟序列化区分开~~

Serializer提供了.is_valid() 和.save()方法~~

DRF 序列化组件第11张DRF 序列化组件第12张
#serializers.py 文件
classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Linux"), (2, "Django"), (3, "Python"))
    chapter = serializers.ChoiceField(choices=CHOICES, source="get_chapter_display", read_only=True)
    w_chapter = serializers.IntegerField(write_only=True)
    pub_time =serializers.DateField()

    publisher = PublisherSerializer(read_only=True)
    user = UserSerializer(many=True, read_only=True)

    users = serializers.ListField(write_only=True)
    publisher_id = serializers.IntegerField(write_only=True)

    defcreate(self, validated_data):
        book = Book.objects.create(title=validated_data["title"], chapter=validated_data["w_chapter"], pub_time=validated_data["pub_time"],                                  publisher_id=validated_data["publisher_id"])
        book.user.add(*validated_data["users"])
        return book
反序列化serializer.py
DRF 序列化组件第13张DRF 序列化组件第14张
classBookView(APIView):
    defget(self, request):
        book_list =Book.objects.all()
        ret = BookSerializer(book_list, many=True)
        returnResponse(ret.data)

    defpost(self, request):
        #book_obj = request.data
        print(request.data)
        serializer = BookSerializer(data=request.data)
        ifserializer.is_valid():
            print(12341253)
            serializer.save()
            returnResponse(serializer.validated_data)
        else:
            return Response(serializer.errors)
反序列化views.py

但前端给我们发送patch请求的时候, 前端传给我们用户需要更新的数据, 我们要对数据进行部分验证.

DRF 序列化组件第15张DRF 序列化组件第16张
classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Linux"), (2, "Django"), (3, "Python"))
    chapter = serializers.ChoiceField(choices=CHOICES, source="get_chapter_display", read_only=True)
    w_chapter = serializers.IntegerField(write_only=True)
    pub_time =serializers.DateField()

    publisher = PublisherSerializer(read_only=True)
    user = UserSerializer(many=True, read_only=True)

    users = serializers.ListField(write_only=True)
    publisher_id = serializers.IntegerField(write_only=True)

    defcreate(self, validated_data):
        book = Book.objects.create(title=validated_data["title"], chapter=validated_data["w_chapter"], pub_time=validated_data["pub_time"],
                                   publisher_id=validated_data["publisher_id"])
        book.user.add(*validated_data["users"])
        returnbook

    defupdate(self, instance, validated_data):
        instance.title = validated_data.get("title", instance.title)
        instance.chapter = validated_data.get("w_chapter", instance.chapter)
        instance.pub_time = validated_data.get("pub_time", instance.pub_time)
        instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
        if validated_data.get("users"):
            instance.user.set(validated_data.get("users"))
        instance.save()
        return instance
PATCH请求serializers.py
DRF 序列化组件第17张DRF 序列化组件第18张
classBookView(APIView):
     defpatch(self, request):
        print(request.data)
        book_id = request.data["id"]
        book_info = request.data["book_info"]
        book_obj = Book.objects.filter(pk=book_id).first()
        serializer = BookSerializer(book_obj, data=book_info, partial=True)
        ifserializer.is_valid():
            serializer.save()
            returnResponse(serializer.data)
        else:
            return Response(serializer.errors)
PATCH请求views.py

验证

如果我们需要对一些字段进行自定义的验证~DRF也给我们提供了钩子方法.

DRF 序列化组件第19张DRF 序列化组件第20张
classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)
    #省略了一些字段 跟上面代码里一样的
    #。。。。。
     defvalidate_title(self, value):
        if "python" not invalue.lower():
            raise serializers.ValidationError("标题必须含有Python")
        return value
单个字段的验证
DRF 序列化组件第21张DRF 序列化组件第22张
classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, "Linux"), (2, "Django"), (3, "Python"))
    chapter = serializers.ChoiceField(choices=CHOICES, source="get_chapter_display", read_only=True)
    w_chapter = serializers.IntegerField(write_only=True)
    pub_time =serializers.DateField()
    date_added = serializers.DateField(write_only=True)
    #新增了一个上架时间字段  
    #省略一些字段。。都是在原基础代码上增加的
    #。。。。。。

    #对多个字段进行验证 要求上架日期不能早于出版日期 上架日期要大
    defvalidate(self, attrs):
        if attrs["pub_time"] > attrs["date_added"]:
            raise serializers.ValidationError("上架日期不能早于出版日期")
        return attrs
多个字段的验证
DRF 序列化组件第23张DRF 序列化组件第24张
defmy_validate(value):
    if "敏感词汇" invalue.lower:
        raise serializers.ValidationError("包含敏感词汇,请重新提交")
    returnvalue


classBookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=32, validators=[my_validate])
    #。。。。。。
    
验证器 validators

ModelSerializer

现在我们已经清楚了Serializer的用法,会发现我们所有的序列化跟我们的模型都紧密相关~

那么,DRF也给我们提供了跟模型紧密相关的序列化器~~ModelSerializer~~

-- 它会根据模型自动生成一组字段

-- 它简单的默认实现了.update()以及.create()方法

定义一个ModelSerializer序列化器

DRF 序列化组件第25张DRF 序列化组件第26张
classBookSerializer(serializers.ModelSerializer):
    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
定义ModelSerializer

外键关系的序列化

注意:当序列化类MATE中定义了depth时,这个序列化类中引用字段(外键)则自动变为只读

DRF 序列化组件第27张DRF 序列化组件第28张
classBookSerializer(serializers.ModelSerializer):
    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        depth = 1
#depth 代表找嵌套关系的第几层
外键关系序列化

自定义字段

我们可以声明一些字段来覆盖默认字段,来进行自定制~

比如我们的选择字段,默认显示的是选择的key,我们要给用户展示的是value。

DRF 序列化组件第29张DRF 序列化组件第30张
classBookSerializer(serializers.ModelSerializer):
    chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    
    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        depth = 1
自定义字段

Meta中其它关键字参数

DRF 序列化组件第31张DRF 序列化组件第32张
classBookSerializer(serializers.ModelSerializer):
    chapter = serializers.CharField(source="get_chapter_display", read_only=True)

    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        depth = 1read_only_fields = ["id"]
        extra_kwargs = {"title": {"validators": [my_validate,]}}
Meta中的参数

post以及patch请求

由于depth会让我们外键变成只读,所以我们再定义一个序列化的类,其实只要去掉depth就可以了

DRF 序列化组件第33张DRF 序列化组件第34张
classBookSerializer(serializers.ModelSerializer):
    chapter = serializers.CharField(source="get_chapter_display", read_only=True)

    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        read_only_fields = ["id"]
        extra_kwargs = {"title": {"validators": [my_validate,]}}
post/patch请求系列化类

SerializerMethodField

外键关联的对象有很多字段我们是用不到的~都传给前端会有数据冗余~就需要我们自己去定制序列化外键对象的哪些字段~~

DRF 序列化组件第35张DRF 序列化组件第36张
classBookSerializer(serializers.ModelSerializer):
    chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    user =serializers.SerializerMethodField()
    publisher =serializers.SerializerMethodField()

    defget_user(self, obj):
        #obj是当前序列化的book对象
        users_query_set =obj.user.all()
        return [{"id": user_obj.pk, "name": user_obj.name} for user_obj inusers_query_set]

    defget_publisher(self, obj):
        publisher_obj =obj.publisher
        return {"id": publisher_obj.pk, "title": publisher_obj.title}

    classMeta:
        model =Book
        fields = "__all__"
        #fields = ["id", "title", "pub_time"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        read_only_fields = ["id"]
        extra_kwargs = {"title": {"validators": [my_validate,]}}
SerializerMethodField

用ModelSerializer改进上面Serializer的完整版

DRF 序列化组件第37张DRF 序列化组件第38张
classBookSerializer(serializers.ModelSerializer):
    dis_chapter = serializers.SerializerMethodField(read_only=True)
    users = serializers.SerializerMethodField(read_only=True)
    publishers = serializers.SerializerMethodField(read_only=True)

    defget_users(self, obj):
        #obj是当前序列化的book对象
        users_query_set =obj.user.all()
        return [{"id": user_obj.pk, "name": user_obj.name} for user_obj inusers_query_set]

    defget_publishers(self, obj):
        publisher_obj =obj.publisher
        return {"id": publisher_obj.pk, "title": publisher_obj.title}

    defget_dis_chapter(self, obj):
        returnobj.get_chapter_display()

    classMeta:
        model =Book
        #fields = "__all__"
        #字段是有序的
        fields = ["id", "title","dis_chapter", "pub_time", "publishers", "users","chapter", "user", "publisher"]
        #exclude = ["user"]
        #分别是所有字段 包含某些字段 排除某些字段
        read_only_fields = ["id", "dis_chapter", "users", "publishers"]
        extra_kwargs = {"title": {"validators": [my_validate,]}, "user": {"write_only": True}, "publisher": {"write_only": True},
                        "chapter": {"write_only": True}}
ModelSerializer

免责声明:文章转载自《DRF 序列化组件》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[转]Lab颜色空间ThinkPhp框架:验证码功能下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

推荐:Java性能优化系列集锦

Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难。随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了。现代JVM持续演进,内建了更为成熟的优化技术、运行时技术和垃圾收集器。与此同时,底层的硬件平台和操作系统也在演化。 目录: 一、Java性能优化系列之一--设计优化 二、J...

Django-rest-framework --- 总结

目录 drf回顾总结 drf基础知识点 1.drf框架安装 安装 drf框架规矩的封装风格 drf请求生命周期 2.接口 3.restful接口规范 4.基于restful规范的原生Django接口 主路由:url.py api组件的子路由:api/url.py 模型层:model.py 后台层:admin.py 数据库迁移 视图层:vi...

sql反模式分析1

第二章:乱穿马路 2.1 目标:存储多值属性 2.2 反模式:格式化的逗号分隔列表 模糊匹配无法使用索引,影响性能;多表关联麻烦,却极大影响性能;执行聚合查询不方便开发和调试;更新某个字段值必须执行两次;字段内容出错数据很难恢复修正;选择一个用不用到的分隔符,无法确认不适用;列表长度限制; 2.3 解决方案:创建一张交叉表,实现两张表的多对多的关联 第三...

Django之缓存、信号和图片验证码、ORM性能

一、 缓存 1、 介绍 缓存通俗来说:就是把数据先保存在某个地方,下次再读取的时候不用再去原位置读取,让访问速度更快。 缓存机制图解 2、Django中提供了6种缓存方式   1. 开发调试   2. 内存   3. 文件   4. 数据库   5. Memcache缓存(python-memcached模块)   6. Memcache缓存(pyl...

sql级联删除与级联更新的思考

 sql级联删除   功能:在删除主表时,自动删除副表(外键约束)相应内容 删除包含主键值的行的操作,该值由其它表的现有行中的外键列引用。在级联删除中,还删除其外键值引用删除的主键值的所有行。 如: create database tempgouse tempgo create table UserInfo(UserId int identity(1,...

MySQL学习笔记——〇一

这里不讲MySQL的原理和连接的方法了,就讲一下如何对数据库进行操作。 用户操作 创建用户 创建用户的方法:我们可以用下面的代码进行用户的创建 create user 'username'@'ip' identified by 'password'; 在上面的代码中,表示创建了用户名为username的用户,用户登录ip限制为ip,密码为password。...