DRF--序列化

简介: DRF--序列化

为什么要用序列化


当我们做前后端分离的项目时,前后端交互一般都是JSON格式的数据,那么我们给前端的数据就要转为JSON格式,就需要我们拿到数据库后的数据进行序列化。在看DRF的序列化之前,先来看看django的序列化

model.py

序列化


DRF的序列化


从上面的例子中可以看出来,这样我们序列化出来的数据,写法很麻烦。所以我们用DRF的序列化,要用别人的序列化就要遵守别人的规则,首先需要在app里注册

INSTALLED_APPS = [
    'django.contrib.admin',
    ...
    'rest_framework',
]

注册好了之后要声明序列化类,在当前app下创建一个py文件

1 from rest_framework import serializers
 2
 3 #  出版社的序列化器,前面的变量要和model里的变量名一样
 4 class PublisherSerializer(serializers.Serializer):
 5     id = serializers.IntegerField()
 6     title = serializers.CharField(max_length=32)
 7
 8
 9 class AuthorSerializer(serializers.Serializer):
10     id = serializers.IntegerField()
11     name = serializers.CharField(max_length=32)
12
13
14 class BookSerializer(serializers.Serializer):
15     id = serializers.IntegerField()
16     title = serializers.CharField(max_length=32)
17     pub_time = serializers.DateField()
18     category = serializers.CharField(source="get_category_display")  # 选择的需要指定source
19
20     publisher = PublisherSerializer()  # 一对多的表
21     authors = AuthorSerializer(many=True)  # 多对多的表需要指定many=True

上面我们就写好了序列化的类,注意:匹配上的字段进行序列化,匹配不上则丢弃,所以前端需要哪些字段就写哪些,如果不写的就不序列化

外键关系的序列化是嵌套的序列化器对象

注意many=True

然后再视图函数里写序列化对象

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from djangoDemo.models import Book  # 导入表
from .serializers import BookSerializer
class BookView(APIView):
    def get(self, request):
        book_queryset = Book.objects.all()
        # 拿出来的是一个queryset,用序列化器进行序列化
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)  # 序列化后的数据在data里

注意:当查询出的数据是一个queryset时,需要加many=True,内部会认为是一个可迭代的对象,会去循环。当查询出的是一条数据时,不需要加many=True,会报错

当我们访问这个接口时,返回的数据就是如下的格式

{
        "id": 1,
        "title": "python从入门到放弃",
        "pub_time": "2019-09-10",
        "category": "python",
        "publisher": {
            "id": 1,
            "title": "清华"
        },
        "authors": [
            {
                "id": 1,
                "name": "马云"
            },
            {
                "id": 2,
                "name": "刘亦菲"
            }
        ]
    }


反序列化


当我们进行post请求的时候,我们需要定义数据格式,然后让前端的妹子传给我们对应的格式。格式确定之后我们还要校验前端妹子传过来的格式和字段,比如字段的类型还有长度,我们不能相信前端妹子的话,妹子说“我没事”。难道就真没事了吗?所以数据校验是必不可少的。

数据格式当然是json格式的,那怎么校验数据呢,在上面我们写了个序列化类,来序列化返回给前端的数据,我们也可以用来校验前端传给我们的数据。因为id是自动递增的,所以前端不需要传,我们也不需要校验,可以加个参数required=False,表示只序列化不反序列化。还有些字段,比如上面的category字段,我们序列化的时候返回的是后面的汉字,而反序列化的时候,我们希望是前面的数字,所以我们需要重写这个字段,如果字段里有read_only=True,表示只序列化。如果是write_only=True,表示只反序列化

返回的数据是上面格式的,我们如果新增数据,希望数据是下面这个格式的

{
        "title": "HTML",
        "pub_time": "2019-09-10",
        "post_category": 1,
        "publisher_id":1,
        "author_list": [1,2]
}

注意,前面的key是序列化器里对应的字段

先来改写序列化器

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)  # 只序列化,不走校验
    title = serializers.CharField(max_length=32)
    pub_time = serializers.DateField()
    category = serializers.CharField(source="get_category_display", read_only=True)  # 只序列化用
    # 因为前端传的是数字,所以需要重写
    post_category = serializers.IntegerField(write_only=True)  # 只反序列化用
    publisher = PublisherSerializer(read_only=True)  # 一对多的表  只序列化用
    authors = AuthorSerializer(many=True, read_only=True)  # 多对多的表需要指定many=True 只序列化用
    publisher_id = serializers.IntegerField(write_only=True)  # 只反序列化用
    author_list = serializers.ListField(write_only=True)  # 只反序列化用
    def create(self, validated_data):
        # validated_data校验通过的数据
        # 通过ORM操作给book表增加数据
        book_obj = Book.objects.create(title=validated_data['title'],
                                       pub_time=validated_data['pub_time'],
                                       category=validated_data['post_category'],
                                       publisher_id=validated_data['publisher_id'])
        book_obj.authors.add(*validated_data['author_list'])  # 这个参数可能是一个列表
        return book_obj

在来改写视图函数,新增post请求

class BookView(APIView):
    def get(self, request):
        book_queryset = Book.objects.all()
        # 拿出来的是一个queryset,用序列化器进行序列化
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)  # 序列化后的数据在data里
    def post(self, request):
        # 确定数据类型以及数据结构
        # 对前端传来的数据进行校验
        book_obj = request.data  # post传来的数据
        ser_obj = BookSerializer(data=book_obj) # 有data参数,表示反序列化
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)  # 返回错误

这样,当我们提交像上面一样的数据格式之后,在看get请求,就返回如下的数据

序列化返回给前端的数据


put反序列化


上面的序列化是post请求的,那我们修改数据的时候可能是只对某一个字段进行修改

路由:

urlpatterns = [
    url(r'^book/$', BookView.as_view()),
    url(r'^book/(?P<id>\d+)', BookEditView.as_view()),
]

在 BookSerializer 序列化类里添加一个update方法

def update(self, instance, validated_data):
    # instance 更新的book_obj对象
    # validated_data 校验通过的数据
    instance.title = validated_data.get("title",instance.title)
    instance.pub_time = validated_data.get("pub_time",instance.pub_time)
    instance.category = validated_data.get("post_category",instance.category)
    instance.publisher_id = validated_data.get("publisher_id",instance.publisher_id)
    if validated_data.get("author_list"):  # 可能有多个值
        instance.author.set(validated_data["author_list"])
    instance.save()  # 保存
    return instance

因为不知道修改的是哪个字段,所以都要写

在写put请求

class BookEditView(APIView):
    def get(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(book_obj)  # 查询出的是一条数据,不需要加 many=True
        return Response(ser_obj.data)
    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        # instance必传,data=request.data前端传的参数,partial=True部分修改
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)  # 返回数据,注意不是ser_obj.validated_data
        return Response(ser_obj.errors)

相关文章
|
6月前
|
JSON 前端开发 API
Django API开发实战:前后端分离、Restful风格与DRF序列化器详解
Django API开发实战:前后端分离、Restful风格与DRF序列化器详解
|
JSON 前端开发 关系型数据库
高频面试题-DRF-序列化-反序列化
Django-drf框架最大的亮点莫过于Serializer序列化器这个操作了, 它极大的简化了程序员在模型类和JSON数据格式之间转换的代码,节省了大量的时间和遍历。
高频面试题-DRF-序列化-反序列化
|
JSON 数据格式 Python
django drf 案例--实现url编码和json和dict格式转化小工具(涉及定义模型类,序列化器,类视图,路由),接口测试
django drf 案例--实现url编码和json和dict格式转化小工具(涉及定义模型类,序列化器,类视图,路由),接口测试
|
XML JSON 前端开发
【Django学习笔记 - 17】:序列化和反序列化(restful接口小案例、DRF的工程搭建、序列化器与序列化、验证、保存)
【Django学习笔记 - 17】:序列化和反序列化(restful接口小案例、DRF的工程搭建、序列化器与序列化、验证、保存)
537 0
【Django学习笔记 - 17】:序列化和反序列化(restful接口小案例、DRF的工程搭建、序列化器与序列化、验证、保存)
|
UED 前端开发
DRF如何序列化外键的字段
我觉得在有些应用场景下,这个操作是有用的,因为可以减少一个AJAX的请求,以增加性能。 当然,是二次请求,还是一次传输。这即要考虑用户体验,还要兼顾服务器性能。 一切是有条件的平衡吧。就算是一次传输,字段少的可以全部传,而字段多的就要自定义啦。
2273 0
|
4月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
1月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
1月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
2月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
2月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。