Django框架深入了解_02(DRF之序列化、反序列化)
序列化:将Python对象准换成json格式的字符串,反之即为反序列化
DRF的序列化使用过程:
使用drf的序列化组件
-1 新建一个序列化类继承Serializer
-2 在类中写要序列化的字段
-在视图中使用序列化的类
-1 实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)
-2 对象.data
-3 return Response(对象.data)
使用示例:
新建Django项目:settings.py文件注册rest_framework,使用MySQL数据库创建数据
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'drf_ser01',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': ''
}
} # __init__.py
import pymysql
pymysql.install_as_MySQLdb()
MySQL数据库连接
from django.db import models # Create your models here. class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(decimal_places=1, max_digits=6)
publish = models.ForeignKey(to='Publish')
author = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author')) class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64, null=True) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField() class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
models
app01新建MySer.py
# 先创建一个BookSer序列化类
from rest_framework import serializers class BookSer(serializers.Serializer):
id = serializers.CharField()
title = serializers.CharField()
publish = serializers.CharField()
author = serializers.CharField()
app01视图函数views.py中
from django.shortcuts import render,HttpResponse,redirect
from app01.MySer import BookSer
from rest_framework.response import Response
from rest_framework.views import APIView
from app01 import models # Create your views here. class Books(APIView):
response = {'code': 100, 'msg': '查询成功'}
def get(self, request):
books = models.Book.objects.all()
books_ser = BookSer(instance=books, many=True)
return Response(books_ser.data)
配路由:
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^books/', views.Books.as_view()),
]
(通过NaviCat创建图书数据,用于查询...)
使用Postman发送get请求,获取到数据库中所有图书信息

可以看出一对多和多对多的外键字段显示的是对象名字,下面进一步使用序列化,让信息显示更完善
-source:可以指定字段(name publish.name),可以指定方法 -SerializerMethodField搭配方法使用(get_字段名字)
publish_detail=serializers.SerializerMethodField(read_only=True)
def get_publish_detail(self,obj):
return {'name':obj.publish.name,'city':obj.publish.city}
更新版本BookSer
from rest_framework import serializers class BookSer(serializers.Serializer):
id = serializers.CharField()
title = serializers.CharField()
publish = serializers.CharField(source='publish.name')
author = serializers.SerializerMethodField()
def get_author(self, obj):
authors = []
for author_obj in obj.author.all():
authors.append({'name': author_obj.name, 'age': author_obj.age})
return authors

补充:
-read_only:反序列化时,不传
-write_only:序列化时,不显示
以上是序列化的一种方式
下面看看序列化的另外一种方式:ModelSerializers:指定了表模型
class Meta:
model=表模型
#要显示的字段
fields=('__all__')
fields=('id','name')
#要排除的字段
exclude=('name')
#深度控制
depth=1
-重写某个字段
在Meta外部,重写某些字段,方式同Serializers
# 序列化方式二:
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ('__all__')

如果只想取其中几个字段,可以进行指定:
# 序列化方式二:
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ['id', 'title']
# fields = ('__all__')

刚才看到__all__,序列化所有字段,查询到的数据里面publish和author都是对应id值,如果需要获取到对应publish和author的关联信息,可以在BookSer内,Meta外重新写字段,方式同serializers
# 序列化方式二:
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
# fields = ['id', 'title']
fields = ('__all__')
publish = serializers.CharField(source='publish.name')
author = serializers.SerializerMethodField()
def get_author(self, obj):
authors = []
for author_obj in obj.author.all():
authors.append({'name': author_obj.name, 'age': author_obj.age})
return authors

改进:
class AuthorSer(serializers.Serializer):
id = serializers.CharField()
name = serializers.CharField()
age = serializers.CharField() # 序列化方式二改进:
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
# fields = ['id', 'title']
fields = ('__all__')
publish = serializers.CharField(source='publish.name')
author = serializers.SerializerMethodField()
def get_author(self, obj):
ret = AuthorSer(obj.author.all(), many=True)
return ret.data

通过post请求新增数据:
对数据进行新增使用反序列化实现,这里反序列化有2种情况进行新增:
使用继承了Serializers序列化类的对象,反序列化(需重写create方法)
from django.db import models # Create your models here. class User(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
choices = (('', 'Super_Admin'), ('', 'General_Admin'), ('', 'General_User') )
user_type = models.CharField(max_length=6, choices=choices, default='') class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(decimal_places=1, max_digits=6)
publish = models.ForeignKey(to='Publish', null=True)
author = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64, null=True) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
class Book(APIView):
def post(self, request):
response = {'code': 100, 'msg': '新增成功'}
# 使用继承了Serializers序列化类的对象,反序列化
book = BookSer(data=request.data)
if book.is_valid():
# 清洗通过的数据,需要在MySer.py中重写create
book.create(book.validated_data)
return Response(response)
# MySer.py class BookSer(serializers.Serializer):
# read_only 反序列化的时候,该字段不传
# 这里id可以不传自增,publish、author不传,当然需要在models里面把不传字段设置为null=True
# author多对多字段不能设置null=True
id = serializers.CharField(read_only=True)
title = serializers.CharField()
price = serializers.CharField()
publish = serializers.CharField(source='publish.id', read_only=True)
author = serializers.SerializerMethodField(read_only=True)
def get_author(self, obj):
ret = AuthorSer(obj.author.all(), many=True)
return ret.data
# 重写create方法,才能在使用Serializer发序列化方法进行新增数据
def create(self, validated_data):
res = models.Book.objects.create(**validated_data)
return res
使用继承了ModelSerializers序列化类的对象,反序列化
from django.db import models # Create your models here. class User(models.Model):
name = models.CharField(max_length=32)
password = models.CharField(max_length=64)
choices = (('', 'Super_Admin'), ('', 'General_Admin'), ('', 'General_User') )
user_type = models.CharField(max_length=6, choices=choices, default='') class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(decimal_places=1, max_digits=6)
publish = models.ForeignKey(to='Publish', null=True)
author = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64, null=True) class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__"
class Book(APIView):
def post(self, request):
response = {'code': 100, 'msg': '新增成功'}
# 使用继承了ModelSerializers序列化类的对象,反序列化
book_ser = BookSer(data=request.data)
if book_ser.is_valid():
book_ser.save()
else:
response['error'] = book_ser.errors['name'][0]
return Response(response)
使用ModelSerializer反序列化save数据后,多对多关联的那张表也会自动关联产生新的数据。
局部校验和全局校验
# MySer.py from rest_framework.exceptions import ValidationError
class BookSer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = "__all__" def validate_title(self, value):
if value.startswith('sb'):
raise ValidationError('不能以sb开头')
return value def validate(self, attrs):
title = attrs.get('title')
price = attrs.get('price')
if title.startswith('禁书') or int(price) <= 15:
raise ValidationError('书名或价格不正常')
return attrs
总结:
-反序列化的校验
-validate_字段名(self,value):
-如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
-如果校验通过直接return value
-validate(self,attrs)
-attrs所有校验通过的数据,是个字典
-如果校验失败,抛出ValidationError
-如果校验通过直接return attrs
Django框架深入了解_02(DRF之序列化、反序列化)的更多相关文章
- Django框架深入了解_04(DRF之url控制、解析器、响应器、版本控制、分页)
一.url控制 基本路由写法:最常用 from django.conf.urls import url from django.contrib import admin from app01 impo ...
- Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)
一.认证组件 使用方法: ①写一个认证类,新建文件:my_examine.py # 导入需要继承的基类BaseAuthentication from rest_framework.authentica ...
- django框架-DRF视图中的request和response
1.Request 相对于django框架,DRF工程的request类则是继承自HttpRequest类,Rest framework提供了parser解释器,用来解释请求中的content_typ ...
- Django框架深入了解_01(Django请求生命周期、开发模式、cbv源码分析、restful规范、跨域、drf的安装及源码初识)
一.Django请求生命周期: 前端发出请求到后端,通过Django处理.响应返回给前端相关结果的过程 先进入实现了wsgi协议的web服务器--->进入django中间件--->路由f分 ...
- DRF框架之使用Django框架完成后端接口(API)的定义
学习DRF框架,首先我们就需要明白为什么要学习这个框架. 接下来我们就先用原生的Django框架来定义一个符合RESTful设计方法的接口(API). RESTful接口的需求如下: GET /boo ...
- 第三百零九节,Django框架,models.py模块,数据库操作——F和Q()运算符:|或者、&并且——queryset对象序列化
第三百零九节,Django框架,models.py模块,数据库操作——F()和Q()运算符:|或者.&并且 F()可以将数据库里的数字类型的数据,转换为可以数字类型 首先要导入 from dj ...
- Django框架之DRF APIView Serializer
一.APIView 我们在使用DjangoRestfulFramework的时候会将每个视图类继承APIView,取代原生Django的View类 APIView的流程分析: rest_framewo ...
- Django drf:序列化增删改查、局部与全局钩子源码流程、认证源码分析、执行流程
一.序列化类的增.删.改.查 用drf的序列化组件 -定义一个类继承class BookSerializer(serializers.Serializer): -写字段,如果不指定source ...
- Python 之 Django框架( Cookie和Session、Django中间件、AJAX、Django序列化)
12.4 Cookie和Session 12.41 cookie Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务 ...
随机推荐
- VisualStudio 2019 Serials
9DP6T-9AGWG-KWV33-9MPC8-JDCVF 7G2HE-JR8KL-ABB9D-Y7789-GLNFL U2PWU-H7D9H-69T3B-JEYC2-3R2NG R8R8P-MTT6 ...
- RESTful API Design: 13 Best Practices to Make Your Users Happy
RESTful API Design: 13 Best Practices to Make Your Users Happy First step to the RESTful way: make s ...
- [BZOJ1191]超级英雄Hero
Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的 多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目,只有当选手正确 ...
- 3D数据采集和重建
3D数据采集和重建是从传感器数据生成三维或时空模型.一般而言,这些技术和理论适用于大多数或所有传感器类型,包括光学,声学,激光扫描,[1]雷达,热学,[2]地震.[3][4] 内容 · ...
- C Primer Plus--C预处理器和C库(1)
目录 预处理符号 明显常量 #define 编译程序之前,先由预处理器检查程序(因此称为预处理器).根据程序中使用的预处理器指令,预处理用符号缩略语所代表的内容替换程序中的缩略语. 预处理器可以根据你 ...
- 最大の和(洛谷 AT2412)
题意 读入n个整数的数列a1,a2,…,an和正整数k(1<=k<=n),请输出连续排列的k个整数的和的最大值 输入 第一行是正整数n(1<=n<=100000)和正整数k(1 ...
- .getCellType()的几种类型值
CellType 类型 值 CELL_TYPE_NUMERIC 数值型 0 CELL_TYPE_STRING 字符串型 1 CELL_TYPE_FORMULA 公式型 2 CEL ...
- TreeMap用法总结
TreeMap用法总结 public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap&l ...
- ICEM-非结构化网格中创建无厚度的面
原版视频下载地址:https://pan.baidu.com/s/1pLazbOf 密码: 4pii
- ICEM-双管
原视频下载地址:http://yunpan.cn/cLHCm7Uejw4eG 访问密码 b8a1