序列化组件

[TOC]

# 模型层
from django.db import models class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField() publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author') def __str__(self):
return self.name class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDatail', to_field='nid', unique=True, on_delete=models.CASCADE) class AuthorDatail(models.Model):
nid = models.AutoField(primary_key=True)
telephone = models.BigIntegerField()
birthday = models.DateField()
addr = models.CharField(max_length=64) class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField() def __str__(self):
return self.name def test(self):
return self.email

一、利用for循环来实现序列化(繁琐)

def get(self, request):
response = {'status': 100, 'data': None}
ll = [{'name': book.name, 'price': book.price} for book in books]
# 返回数据是json格式数据
response['data'] = ll
# safe = True 表示数据可以是列表
return JsonResponse(response, safe=False)

二、利用Django提供的序列化组件(不可控需要的字段)

Django内置的serializers

from django.core import serializers

def get(self,request):
books = models.Book.objects.all()
ret=serializers.serialize('json','queryset对象')
#ret就是序列化之后的字符串了,不需要再序列化了
return HttpResponse(ret)

三、利用drf提供的序列化组件

1、基于Serializer类实现序列化——基本语法

-1 先导入
from rest_framework.serializers import Serializer
from rest_framework import serializers
-2 写一个类,继承Serializer
-3 在类内部写属性:
name=serializers.CharField()
-4 使用:
先生成对象,需要传参数 instance:要序列化的对象(可能是queryset,也可能是单个对象)
many:如果是queryset---True,,如果是单个对象--False
-5 序列化的数据:对象.data --->是一个字典
from rest_framework.views import APIView
from rest_framework import serializers class BookSerializer(serializers.Serializer):
name = serializers.CharField() class Book(APIView):
def get(self, request):
# 要序列化的对象(可以是queryset,也可以是单个对象)
# book = models.Books.objects.filter(name='红楼梦').first()
# ser = BookSerializer(instance=book,many=False)
books = models.Books.objects.all()
ser = BookSerializer(instance=books, many=True)
data = ser.data
return JsonResponse(data, safe=False)

2、基于Serializer类实现序列化——高级语法

(1)非关联字段或一对多字段

  • 可以不用source,直接用 字段名 当变量名,必须为字段名
  • 也可以用 source来指定需要的目标字段 (推荐,尽量让字段名不要泄露)
  • source也可以用来指定模型层中的方法
  • 一对多关联关系,可以在 source 中用 .来指定字段,例如取出版社名字,用 source='publish.name'
from rest_framework.views import APIView
from rest_framework import serializers class BookSerializer(serializers.Serializer):
# 利用source来指定魔表字段,给key取别名
aaa = serializers.CharField(source='name') # 等价于 name = serializers.CharField()
price = serializer.CharField()
publish_name = serializer.CharField(source='publish.name')
# source 也可以用来指定模型层中的方法
t = serializer.CharField(source='publish.test') class Book(APIView):
def get(self, request):
books = models.Books.objects.all()
ser = BookSerializer(instance=books, many=True)
data = ser.data
return JsonResponse(data, safe=False)

(2)一对多或者多对多字段

  • 多对多要用SerializerMethodField(),然后定义一个get_变量名的方法,方法名字必须为 get_变量名
  • get_变量名方法要传参,传入当前对象,例如在 BookSerializer 中就是book对象
  • get_变量名方法中,也可以对数据进行序列化,例如取书的所有作者,就可以对作者序列化然后 return
from rest_framework.views import APIView
from rest_framework import serializers # 用于对author的数据进行序列化
class AuthorSerializer(serliazer.Serializer):
name = serializer.CharField()
age = serializer.CharField() class BookSerializer(serializers.Serializer):
# 利用source来给key取别名
aaa = serializers.CharField(source='name') # 等价于 name = serializers.CharField()
price = serializer.CharField() # book和publish是一对多的关系,也可以用SerializerMethodField
publish = serializer.SerializerMethodField()
def get_publish(self, book):
pub = book.publish.name
return pub # book和authors是多对多的关系,用SerializerMethodField
au = serializer.SerializerMethodField()
def get_au(self, obj):
aus = obj.authors.all()
ll = []
for obj_au in aus:
ll.append({'au_name':obj_au.name,'au_age':obj_au.age})
return ll # 也可以在方法中使用序列化类序列化
'''
def get_au(self, book):
# 获取这本书的所有作者
aus = book.authors.all()
# 可以在方法中对authors的数据进行序列化
au_ser = AuthorSerializer(aus,many=True)
return au_ser.data
''' class Book(APIView):
def get(self, request):
books = models.Books.objects.all()
ser = BookSerializer(instance=books, many=True)
data = ser.data
return JsonResponse(data, safe=False)

3、基于ModelSerializer类实现序列化

(1)基本语法

from app01.models import Book

# 这样序列化得到的数据,authors是中都是author_id
class BookSerializer(serializer.ModelSerializer):
class Meta:
model = Book
fields = '__all__'

(2)重写属性

from app01.models import Book

# 这样序列化得到的数据,authors中都是author_id,publish也是publish_id
class BookSerializer(serializer.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# 重写属性authors和publish
puhlish = serializer.CharField(source='publish.name')
authors = serializers.SerializerMethodField()
def get_authors(self,book):
aus = book.authors.all()
# 可以在方法中对authors的数据进行序列化
au_ser = AuthorSerializer(aus,many=True)
return au_ser.data

(3)其他属性

  • fields = ['id','name'] ---------> 指定序列化这两个字段
  • exclude = ['publish','create_time'] ----------> 除了这两个字段外,其余的序列化
  • depth = 2 ----------> 指定深度,即跨表。值为1表示跨一次表;值为2表示跨两次表
class BookSerializer(serializers.ModelSerializer):
# 必须写一个内部类,名字叫Meta
class Meta:
model = Book
# fields = '__all__'
# 指定只取这两个字段
fields = ['nid','name']
# 去掉指定的字段
# exclude=['publish','authors']
# fields,跟exclude不能连用
# 指定深度(官方建议小于10,我给你的建议小于3)
depth = 2

4、HyperlinkedIdentityField(带链接的序列化)-----很少用

# url层
url(r'book/$',views.Book.as_view()),
url(r'publish/(?P<pk>\d+)',views.Publish.as_view(),name='ttt') # view层
# 定义一个序列化类
class BookSerializer(serializers.Serializers):
name = serializers.CharField()
# view_name:路由的名字;lookup_field:根据表的哪个字段;lookup_url_kwarg:反向解析有名分组的名字。------lookup_field与lookup_url_kwarg相当于是key与value
publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id',lookup_url_kwarg='pk')
# 最后得到的链接是: http://127.0.0.1:8000/publish/1 # CBV
class Book(APIView):
def get(self, request):
books = models.Book.objects.all()
# 必须要传过去request,以便在链接中拼接域名
ser = BookSerializer(books, many=True, context={'request':request})
return JsonResponse(ser.data,safe=False)

5、序列化组件之请求数据校验和保存功能

  • 序列化类必须继承ModelSerializer类,只有该类可以指定数据保存修改的目标表模型。倘若一定要继承Serializer类,可以通过重写save方法,来实现保存和修改数据

  • 序列化组件校验和forms组件类似

  • 钩子函数抛异常,异常是 rest_framework.exceptions 下的 ValidationError

  • 新增数据:
    新增数据,将数据传入实例化类产生对象,通过is_valid()校验,校验通过,利用序列化对象的save()方法保存

    ser=BookSerializer(data=request.data)
    if ser.is_valid():
    ser.save()
  • 修改数据:
    修改数据一定要在实例化序列化类的时候传参instance='要修改的对象'指定要修改的对象

    ret = models.Book.objects.filter(name=request.data.get('name')).first()
    ser=BookSerializer(data=request.data, instance=ret')
    if ser.is_valid():
    ser.save()
# 定义一个序列化类
from rest_framework.exceptions import ValidationError
class BookSerializer(serializerss.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# 校验和forms组件类似
name = serializers.CharField(max_length=10,required=True,error_message={'max_length':最长不能超过10位,'requered':'必须填'})
# 局部钩子,value是前端传过来的数据
def validate_name(self,value):
if value.startswith('aa'):
raise ValidationError('不能以aa开头')
return value
# 全局钩子 ,这里的value是上面验证通过后的所有数据构成的字典
def validate(self,value):
pwd = value.get('pwd')
re_pwd = value.get('re_pwd')
if pwd == re_pwd:
return value
raise ValidationError('两次密码不一致')
# CBV
# 1. 新增对象
class Book(APIView):
def post(self, request, *args, **kwargs):
response = {'status': 100, 'msg': None}
data = request.data
ser = BookSerializer(data=data)
if ser.is_valid():
ser.save()
response['msg'] = '创建成功'
else:
response['status'] = 101
response['msg'] = ser.errors
return JsonResponse(response, safe=False)
# CBV
# 2.修改数据
class Book(APIView):
def put(self, request, *args, **kwargs):
response = {'status': 100, 'msg': None}
data = request.data
ser = BookSerializer(data=data,instance=)
if ser.is_valid():
ser.save()
response['msg'] = '创建成功'
else:
response['status'] = 101
response['msg'] = ser.errors
return JsonResponse(response, safe=False)

Django框架(十九)—— drf:序列化组件(serializer)的更多相关文章

  1. 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)

    知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...

  2. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

  3. DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验

    序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ...

  4. 任务三十九:UI组件之冻结行列表格

    任务三十九:UI组件之冻结行列表格 面向人群: 有一定JavaScript基础 难度: 中 重要说明 百度前端技术学院的课程任务是由百度前端工程师专为对前端不同掌握程度的同学设计.我们尽力保证课程内容 ...

  5. 微信小程序把玩(二十九)video组件

    原文:微信小程序把玩(二十九)video组件 视频播放组件与图片加载组件也没啥差别,使用起来也没啥注意的 重要属性: wxml <!--监听button点击事件--> <button ...

  6. 微信小程序把玩(十九)radio组件

    原文:微信小程序把玩(十九)radio组件 radio组件为单选组件与radio-group组合使用,使用方式和checkbox没啥区别 主要属性: wxml <!--设置监听器,当点击radi ...

  7. drf框架 - 序列化组件 | Serializer

    序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...

  8. Django(45)drf序列化类的使用(Serializer)

    前言 上一篇文章我们讲述了序列化,这篇就带大家一起来实现以下序列化 Serializer 我们使用序列化类Serializer,我们来看下源码结构,这里推荐使用pycharm左边导航栏的Structu ...

  9. cvb源码分析,resful规范,drf,drf序列化组件,95

    1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...

  10. DRF 序列化组件

    Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...

随机推荐

  1. DOM选择器

    DOM选择器分为:id.class.name.tagname.高级.关系选择器;(返回的都是标签) 一:元素节点选择器: 1. id: 返回的是单个对象 <body> <div cl ...

  2. python 类和对象上

    面向对象 Object Oriented 面向对象的学习: 面向对象的语法(简单,记忆就可以搞定) 面向对象的思想(稍难,需要一定的理解) 面向过程和面向对象的区别 面向过程开发,以函数作为基本结构使 ...

  3. [CF895E] Eyes Closed(线段树,期望)

    Desctiption 传送门:Portal 大致题意: 给你一个序列, 支持两种操作: 1 l1 r1 l2 y2 在\([l1, r1]\)随机选择一个数a, \([l2, r2]\) 内随机选择 ...

  4. python第三方库安装失败处理方法

    各位道友,是不是在使用pip 命令安装第三方库遇到了以下情形呢? 这种情况可真让人头疼啊..经过几番周折,终于找到了认为最有效的解决方法 首先 先把要安装的包下载下来,不管用什么方式 在这里我用的迅雷 ...

  5. 【目录】redis 系列篇

    随笔分类 - redis 系列篇 redis 系列27 Cluster高可用 (2) 摘要: 一. ASK错误 集群上篇最后讲到,对于重新分片由redis-trib负责执行,关于该工具以后再介绍.在进 ...

  6. 解决 Failed to load class "org.slf4j.impl.StaticLoggerBinder"

    我们在使用日志记录网站或者应用时,有时候启动会出现这个告警: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder&q ...

  7. 转载:tomcat性能的优化

    考虑一下这种场景,你开发了一个应用,它有十分 优秀的布局设计,最新的特性以及其它的优秀特点.但是在性能这方面欠缺,不管这个应用如何都会遭到客户拒绝.客户总是期望它们的应用应该有更好的性能.如 果你在产 ...

  8. ida吧

    经过IDA反编译后的代码是:int __cdecl Ompress(void *Dst, int a2, int a3, int a4)//dst( [esp+24h][ebp+4h] );a2([e ...

  9. RIDE使用介绍

    [转载] RIDE是一款专门用来编辑Robot Framework用例的软件,用Python编写并且开源.当我们针对一个系统编写好一套用例后,每当我们对系 统做一些更改的时候,便可以把已经写好的用例拿 ...

  10. Java集合类里面最基本的接口

    Collection:代表一组对象,每一个对象都是它的子元素. Set:不包含重复元素的Collection. List:有顺序的Collection,并且可以包含重复元素. Map:可以把键(key ...