为什么要用序列化组件

当我们做前后端分离的项目~~我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式。

那么我们给前端数据的时候都要转成json格式,那就需要对我们从数据库拿到的数据进行序列化。

接下来我们看下django序列化和rest_framework序列化的对比~~

Django的序列化方法

class BooksView(View):
def get(self, request):
book_list = Book.objects.values("id", "title", "chapter", "pub_time", "publisher")
book_list = list(book_list)
# 如果我们需要取外键关联的字段信息 需要循环获取外键 再去数据库查然后拼接成我们想要的
ret = []
for book in book_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)
return HttpResponse(ret) # json.JSONEncoder.default()
# 解决json不能序列化时间字段的问题
class MyJson(json.JSONEncoder):
def default(self, field):
if isinstance(field, datetime.datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field, datetime.date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self, field)

.values 序列化结果

from django.core import serializers

# 能够得到我们要的效果 结构有点复杂
class BooksView(View):
def get(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

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

序列化

class BookSerializer(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()

第一步 声明序列化类

from rest_framework.views import APIView
from rest_framework.response import Response class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ret = BookSerializer(book_list, many=True)
return Response(ret.data)

第二步 序列化对象

外键关系的序列化

# by gaoxin
from rest_framework import serializers
from .models import Book class PublisherSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=32) class UserSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=32)
age = serializers.IntegerField() class BookSerializer(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()方法~~

# serializers.py 文件
class BookSerializer(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) def create(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

class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
ret = BookSerializer(book_list, many=True)
return Response(ret.data) def post(self, request):
# book_obj = request.data
print(request.data)
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
print(12341253)
serializer.save()
return Response(serializer.validated_data)
else:
return Response(serializer.errors)

反序列化views.py

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

class BookSerializer(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) def create(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 def update(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

class BookView(APIView):
def patch(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)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors)

PATCH请求views.py

验证

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

class BookSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=32)
# 省略了一些字段 跟上面代码里一样的
# 。。。。。
def validate_title(self, value):
if "python" not in value.lower():
raise serializers.ValidationError("标题必须含有Python")
return value

单个字段的验证

class BookSerializer(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)
# 新增了一个上架时间字段
# 省略一些字段。。都是在原基础代码上增加的
# 。。。。。。 # 对多个字段进行验证 要求上架日期不能早于出版日期 上架日期要大
def validate(self, attrs):
if attrs["pub_time"] > attrs["date_added"]:
raise serializers.ValidationError("上架日期不能早于出版日期")
return attrs

多个字段的验证

def my_validate(value):
if "敏感词汇" in value.lower:
raise serializers.ValidationError("包含敏感词汇,请重新提交")
return value class BookSerializer(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序列化器

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段

定义ModelSerializer

外键关系的序列化

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

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段
depth = 1
# depth 代表找嵌套关系的第几层

外键关系序列化

自定义字段

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

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

class BookSerializer(serializers.ModelSerializer):
chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段
depth = 1

自定义字段

Meta中其它关键字参数

class BookSerializer(serializers.ModelSerializer):
chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段
depth = 1
read_only_fields = ["id"]
extra_kwargs = {"title": {"validators": [my_validate,]}}

Meta中参数

post以及patch请求

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

class BookSerializer(serializers.ModelSerializer):
chapter = serializers.CharField(source="get_chapter_display", read_only=True) class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段
read_only_fields = ["id"]
extra_kwargs = {"title": {"validators": [my_validate,]}}

post/patch请求序列化类

SerializerMethodField

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

class BookSerializer(serializers.ModelSerializer):
chapter = serializers.CharField(source="get_chapter_display", read_only=True)
user = serializers.SerializerMethodField()
publisher = serializers.SerializerMethodField() def get_user(self, obj):
# obj是当前序列化的book对象
users_query_set = obj.user.all()
return [{"id": user_obj.pk, "name": user_obj.name} for user_obj in users_query_set] def get_publisher(self, obj):
publisher_obj = obj.publisher
return {"id": publisher_obj.pk, "title": publisher_obj.title} class Meta:
model = Book
fields = "__all__"
# fields = ["id", "title", "pub_time"]
# exclude = ["user"]
# 分别是所有字段 包含某些字段 排除某些字段
read_only_fields = ["id"]
extra_kwargs = {"title": {"validators": [my_validate,]}}

SerializerMethodField

用ModelSerializer改进上面Serializer的完整版

class BookSerializer(serializers.ModelSerializer):
dis_chapter = serializers.SerializerMethodField(read_only=True)
users = serializers.SerializerMethodField(read_only=True)
publishers = serializers.SerializerMethodField(read_only=True) def get_users(self, obj):
# obj是当前序列化的book对象
users_query_set = obj.user.all()
return [{"id": user_obj.pk, "name": user_obj.name} for user_obj in users_query_set] def get_publishers(self, obj):
publisher_obj = obj.publisher
return {"id": publisher_obj.pk, "title": publisher_obj.title} def get_dis_chapter(self, obj):
return obj.get_chapter_display() class Meta:
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

 
 
 

django rest_framework Serializers 序列化组件的更多相关文章

  1. Serializers 序列化组件

    Serializers 序列化组件   为什么要用序列化组件 当我们做前后端分离的项目~~我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 那么我们给前端数据的时候都要转 ...

  2. Django-Rest-Framework的序列化之serializers 序列化组件

    Django-Rest-Framework的序列化之serializers 序列化组件 restful framework 正常的序列化 from django.http import HttpRes ...

  3. rest_framework之序列化组件

    什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有form组件帮我们去做数据校验 我们有模板语法,从数据库取出的queryset对象不需要人为去转格式 当我们写前后端分离项 ...

  4. [Django REST framework - 序列化组件、source、钩子函数]

    [Django REST framework - 序列化组件.source.钩子函数] 序列化器-Serializer 什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有f ...

  5. DRF框架之 serializers 序列化组件

    1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式 2. DRF框架自带序列化的工具: serializers 3. DRF框架 serializers ...

  6. drf3 Serializers 序列化组件

    为什么要用序列化组件 做前后端分离的项目,我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 给前端数据的时候都要转成json格式,那就需要对从数据库拿到的数据进行序列化. ...

  7. 【转】Serializers 序列化组件

    https://www.cnblogs.com/MayDayTime/p/9890582.html 为什么要用序列化组件 当我们做前后端分离的项目~~我们前后端交互一般都选择JSON数据格式,JSON ...

  8. Django 之restfromwork 序列化组件实现数据增删查改

    rest-framework序列化之Serializer models.py from django.db import models # Create your models here. class ...

  9. django rest framework 序列化组件总结

    序列化组件总结 一. 序列化组件本质上为了实现前后端分离,而进行json序列化的一个组件形式,极大方便了解析数据的作用 二. 所有序列化是基于APIView 解析器实现的,通过内部的多继承关系方便实现 ...

随机推荐

  1. mongodb批量更新某个字段

    查询出hospitalName是xx医院和openId以2开头的所有记录,并且更新my_booking表中的payType为1. db.getCollection('my_booking').find ...

  2. vue教程2-07 自定义指令

    vue教程2-07 自定义指令 自定义指令: 一.属性: Vue.directive(指令名称,function(参数){ this.el -> 原生DOM元素 }); <div v-re ...

  3. 在Ubuntu 16.04上利用Jexus+.Net Core+Linux版SQL Server部署ZKEACMS.Core

    百度传课视频地址:https://chuanke.baidu.com/v5849090-223278-1498090.html 一.SQL Server on Linux的安装 官方文档:https: ...

  4. Redis笔记(3)多数据库实现

    1.前言 本章介绍redis的三种多服务实现方式,尽可能简单明了总结一下. 2.复制 复制也可以称为主从模式.假设有两个redis服务,一个在127.0.0.1:6379,一个在127.0.0.1:1 ...

  5. 平衡二叉树-AVL树(LL、RR、LR、RL旋转)

    平衡二叉树的定义: 任意的左右子树高度差的绝对值不超过1,将这样的二叉树称为平衡二叉树,二叉平衡树前提是一个二叉排序树. 平衡二叉树的插入: 二叉平衡树在插入或删除一个结点时,先检查该操作是否导致了树 ...

  6. Elasticsearch5.3.1 IK分词,同义词/联想搜索设置

    [大数据]-Elasticsearch5.3.1 IK分词,同义词/联想搜索设置  原文地址:http://www.cnblogs.com/NextNight/p/6837407.html --题外话 ...

  7. Redis随笔(五)Jedis、jedisCluster的使用

    1.Jedis客户端 https://redis.io/clients 2.Jedis源码包与使用介绍 https://github.com/xetorthio/jedis 3.项目中使用 通过mav ...

  8. Git学习系列之Debian或Ubuntu上安装Git详细步骤(图文详解)

    前言 最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Win ...

  9. Element ui tree树形控件获取当前节点id和父节点id

    低版本Element ui tree树形控件获取当前节点id和父节点id的方法:点击查看 最新版本Element ui tree树形控件获取当前节点id和父节点id教程: 1.找到node_modul ...

  10. spring boot 自动更新静态文件和后台代码 -- 热部署

    在spring boot使用的过程中, 发现我修改了静态文件, 前台刷新后, 没有任何变化, 必须重新启动, 才能看到, 这简直不能让人接受. 那有什么方法来解决这个问题呢. Baidu之后, 得到了 ...