1.序列化类常用字段和字段参数

1.1 常用字段类

1.BooleanField
2 NullBooleanField
3 CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
4 EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
5 RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
6 SlugField SlugField(max_length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
7 URLField URLField(max_length=200, min_length=None, allow_blank=False)
8 UUIDField UUIDField(format=’hex_verbose’) format: 1)
9 IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
10 IntegerField IntegerField(max_value=None, min_value=None)
11 FloatField FloatField(max_value=None, min_value=None)
12 DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
13 DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
14 DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
15 TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
16 DurationField DurationField()
17 ChoiceField ChoiceField(choices) choices与Django的用法相同
18 MultipleChoiceField MultipleChoiceField(choices)
19 FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
20 ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

1.2重要字段类型

CharField
IntegerField
DecimalField
DateTimeField
BooleanField
ListField
DictField

1.3 常用字段参数

1.CharField及其子类(哪些类的父类是CharField需要在源码中查看)的字段参数:
max_length:最大长度
min_length:最小长度
allow_blank:是否允许为空
trim_whitespace 是否截断空白字符 2.InterField参数:
max_value:最大值
min_value:最小值 3.所有字段都有的的参数:
required:表明该字段在反序列化时必须输入,默认True
default:反序列化时使用的默认值
allow_null:表名该字段是否允许传入None,默认Flase
validators:该字段使用的验证器
error_messages:包含错误编号与错误信息的字典
label:用于HTML展示API页面时,显示的字段名称
help_text:用于HTML展示API页面时,显示的字段帮助提示信息 read_only:表明该字段仅用于序列化输出,默认Flase
write_only:表明该字段仅用于反序列化的输入,默认Flase 4.反序列化校验执行流程:
1.先执行字段自身的校验规则:max_length,max_value
2.再执行验证器validators
3.局部钩子校验规则
4.全局钩子校验规则

2.序列化高级用法之source

models.py:
先创建表,表之间存在数据库层面的联系:
from django.db import models class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) serializer.py:
from rest_framework import serializers class BookSerializer(serializers.Serializer):
# 自有字段,直接点名字,通过sourse可以指定models.py中某张表的字段
name_zzz = serializers.CharField(max_length=8,source='name')
real_price = serializers.CharField(source='price')
# 一对多,需要先点外键名到那张表,再点那张表的名字
publish = serializers.CharField(source='publish.name')
# 多对多,不能用sourse
authors = serializers.CharField() views.py:
from app01.serializer import BookSerializer
from .models import Book
from rest_framework.response import Response
from rest_framework.views import APIView class BookView(APIView):
def get(self,request):
book_queryset = Book.objects.all()
ser = BookSerializer(instance=book_queryset,many=True)
return Response(ser.data)
"""
通过以上代码演示效果:在serializer.py中无论字段名起什么,只要括号中的source对应models某张表中的某些字段名,在前端就可以显示该名字。它们之间在views.py中通过视图类连接。
"""

3.序列化高级用法之定制字段的两种方式

以上代码存在局限性:首先我们查到出版社,但是我们只能拿到出版社姓名,无法拿到出版社其他信息,其次多对多关系的作者信息我们没法拿到。我们需要通过以下方法来解决。

3.1SerializerMethodField定制

SerializerMethodField是一个定制返回格式的字段类型,该字段类型中不需要填写任何参数,但是方法需要通过写函数来定制指定的返回的格式。返回的数据遵循restful规范:一对多显示字典,多对多显示列表套字典。
serializer.py:
from rest_framework import serializers class BookSerializer(serializers.Serializer):
name_zzz = serializers.CharField(max_length=8, source='name')
real_price = serializers.CharField(source='price') publish_detail = serializers.SerializerMethodField()
# 函数名要和字段名保持一致,该字段名也是前端展示的字段名
def get_publish_detail(self, obj):
return {'name': obj.publish.name, 'addr': obj.publish.addr} author_list = serializers.SerializerMethodField() def get_author_list(self,obj):
l = []
for author_obj in obj.authors.all():
l.append({'name':author_obj.name,'phone':author_obj.phone})
return l
models.py以及views.py代码和上步一样。

3.2在表模型中定制

moodels.py:
from django.db import models class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
# 在表模型中定制的函数名要和serializer.py中的字段名保持一致。
@property
def publish_detail(self):
return {'name':self.publish.name,'addr':self.publish.addr}
# 定制的函数要用@property修饰,可以将方法伪装成一个数据。
@property
def author_list(self):
l = []
for author_obj in self.authors.all():
l.append({'name':author_obj.name,'phone':author_obj.phone})
return l class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) seriializer.py:
from rest_framework import serializers class BookSerializer(serializers.Serializer):
name_zzz = serializers.CharField(max_length=8, source='name')
real_price = serializers.CharField(source='price')
#DictField和ListField用来接收表格类中返回的数据中的字典类型和列表类型
publish_detail = serializers.DictField() author_list = serializers.ListField()

4.多表关联反序列化保存

4.1 反序列化字段校验步骤

1.字段自己的:name = serializers.CharField(max_length=8, error_messages={'max_length': '太长了'})
2.validators=[方法](使用频率较低)
3.局部钩子
4.全局钩子
"""
代码走到if ser.is_valid():时就会走以上反序列化校验代码。
"""

4.2 新增图书接口

# 前端传入数据的格式:{"name":"新阿q正传","price":"88.66","publish":1,"authors":[2]}
models.py:
from django.db import models class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author') @property
def publish_detail(self):
return {'name':self.publish.name,'addr':self.publish.addr} @property
def author_list(self):
l = []
for author_obj in self.authors.all():
l.append({'name':author_obj.name,'phone':author_obj.phone})
return l class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) seriializer.py:
from rest_framework import serializers
from .models import Book class BookSerializer(serializers.Serializer):
# name和price即用来做序列化,也用来做反序列化,既读又写,所以不用加read_only,write_only
name = serializers.CharField(max_length=8)
price = serializers.CharField() # 用来做序列化,所以要加上read_only=True
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True) # 用来做反序列化,要加上write_only=True,如果不加会在前端看到该字段
publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True) # 新增要重写create方法
def create(self, validated_data):
# print(validated_data) {'name': '阿q正传', 'price': '66.66', 'publish': '1', 'authors': [1, 2]}
# 因为前端上传的是publish的id,所以需要用publish_id=validated_data.get('publish')来新增,如果是对象可以直接用publish新增
# 取数据的键需要和前端传过来字典的键保持一致
book_obj = Book.objects.create(name=validated_data.get('name'),price=validated_data.get('price'),publish_id=validated_data.get('publish'))
# 第三张表要手动写代码新增,一个*数打散列表,两个*用来打散字典
book_obj.authors.add(*validated_data.get('authors'))
return book_obj views.py:
class BookView(APIView):
def get(self,request):
book_queryset = Book.objects.all()
ser = BookSerializer(instance=book_queryset,many=True)
return Response(ser.data) def post(self,request):
# print(request.data)
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'新增成功'})
else:
return Response({'code':101,'msg':ser.errors}) 前端数据上传尽量使用JSON格式,发现数据新增成功:

4.3 修改图书接口

# 前端传入数据的格式:{"name":"新阿q正传","price":"88.66","publish":1,"authors":[2]}

models.py:
from django.db import models class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author') @property
def publish_detail(self):
return {'name':self.publish.name,'addr':self.publish.addr} @property
def author_list(self):
l = []
for author_obj in self.authors.all():
l.append({'name':author_obj.name,'phone':author_obj.phone})
return l class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) views.py:
class BookDetailView(APIView):
def put(self,request,pk):
book_obj = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data,instance=book_obj)
if ser.is_valid():
# save需要手动在BookSerializer类中写update方法
ser.save()
return Response({'code':100,'msg':'修改成功'})
else:
return Response({'code':101,'msg':ser.errors}) serializer.py:
from rest_framework import serializers
from .models import Book class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField() # 用来做序列化
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True) # 用来做反序列化
publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True) def create(self, validated_data):
print(validated_data)
book_obj = Book.objects.create(name=validated_data.get('name'),price=validated_data.get('price'),publish_id=validated_data.get('publish'))
book_obj.authors.add(*validated_data.get('authors'))
return book_obj def update(self, instance, validated_data):
# print(validated_data) # {'name': '新阿q正传', 'price': '88.66', 'publish': '1', 'authors': [2]}
# uodate方法中instance就是book对象
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish_id = validated_data.get('publish') #多对多关系在第三张表上,最好先删除,再写入
instance.authors.clear()
instance.authors.add(*validated_data.get('authors'))
# update方法写完依旧要用修改后的对象点save(),然后返回
instance.save()
return instance

5.ModelSerializer使用

ModelSerializer继承自Serializer,完成了很多操作,是之前BookSerializer的简化版:
-跟表模型强关联
-大部分请求,不用写create和update了 serializer.py:
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Book class BookSerializer(serializers.ModelSerializer):
class Meta:
# 和Book表绑定
model = Book
# 中括号内的字段名要和extra_kwargs中的字段名保持一致,并且和models.py中的Book表中的字段名保持一致。
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'authors']
# 定制限制信息
extra_kwargs = {
'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True}
}
# 写钩子函数,要和class Meta:保持相同的缩进
def validate_name(self, name):
if name.startswith('sb'):
raise ValidationError('不能sb') else:
return name models.py:
from django.db import models class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32) publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author') @property
def publish_detail(self):
return {'name':self.publish.name,'addr':self.publish.addr} @property
def author_list(self):
l = []
for author_obj in self.authors.all():
l.append({'name':author_obj.name,'phone':author_obj.phone})
return l class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11) views.py:
from app01.serializer import BookSerializer
from .models import Book
from rest_framework.response import Response
from rest_framework.views import APIView class BookView(APIView):
def get(self,request):
book_queryset = Book.objects.all()
ser = BookSerializer(instance=book_queryset,many=True)
return Response(ser.data) def post(self,request):
# print(request.data)
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'新增成功'})
else:
return Response({'code':101,'msg':ser.errors}) class BookDetailView(APIView):
def put(self,request,pk):
book_obj = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data,instance=book_obj)
if ser.is_valid():
ser.save()
return Response({'code':100,'msg':'修改成功'})
else:
return Response({'code':101,'msg':ser.errors})

drf-序列化字段及参数、序列化和反序列化高级用法、ModelSerializer使用的更多相关文章

  1. MyBatis动态传入表名,字段名参数的解决办法---statementType用法

    statementType="STATEMENT" 要实现动态传入表名.列名,需要做如下修改 添加属性statementType="STATEMENT" 同时s ...

  2. 0012 基于DRF框架开发(04 序列化器的字段与选项)

    1 常用字段类型 字段 构造方式 BooleanField BooleanField() NullBooleanField NullBooleanField() CharField CharField ...

  3. DRF序列化和反序列化(二:ModelSerializer)

    一: rest_framework 中 serializers.Serializer的不方便之处(以下简称Serializer) a:需要定义每一个字段,并且这个字段是和models字段及其类似. b ...

  4. DRF(2) - 解析器,序列化组件使用(GET/POST接口设计)

    一.DRF - 解析器 1.解析器的引出 我们知道,浏览器可以向django服务器发送json格式的数据,此时,django不会帮我们进行解析,只是将发送的原数据保存在request.body中,只有 ...

  5. Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串

    原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...

  6. JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法

    Jackson是Spring Boot默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的,没有这种限制.它提供了很 ...

  7. Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称

    手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...

  8. Python之Suds库调用WCF时复杂参数序列化

    今天主要做自动化测技术支持工作,最近一直在做接口自动化这块,前些天在研究将web页面模拟http进行接口自动化,这周杭州那边想测试WCF服务,所以这两天一直在探索.遇到的第一个问题就是服务参数传参序列 ...

  9. Python之Suds库调用WCF实现复杂参数序列化

    今年主要做自动化测技术支持工作,最近一直在做接口自动化这块,前些天在研究将web页面模拟http进行接口自动化,这周杭州那边想测试WCF服务,所以这两天一直在探索.遇到的第一个问题就是服务参数传参序列 ...

  10. 编写高质量代码改善C#程序的157个建议——建议54:为无用字段标注不可序列化

    建议54:为无用字段标注不可序列化 序列化是指这样一种技术:把对象转变成流.相反过程,我们称为反序列化.在很多场合都需要用到这项技术. 把对象保存到本地,在下次运行程序的时候,恢复这个对象. 把对象传 ...

随机推荐

  1. Oracle用户创建及删除

    偶尔会用到,记录.分享. 1. Oracle用户创建 #创建用户表空间create tablespace $username datafile '/u01/app/oracle/oradata/ufg ...

  2. selenium被某些网页检测不允许正常访问、登录等,解决办法

    网站通过什么方式检测 function b() { return "$cdc_asdjflasutopfhvcZLmcfl_"in u || d.webdriver } 通过上方的 ...

  3. C#winform使用NOPI读取Excel读取图片

    需求:在Winform使用NOPI做导入时候,需要导入数据的同时导入图片. 虽然代码方面不适用(我好像也没仔细看过代码),但是感谢大佬给了灵感http://www.wjhsh.net/IT-Ramon ...

  4. 2 c++编程-核心

    ​ 重新系统学习c++语言,并将学习过程中的知识在这里抄录.总结.沉淀.同时希望对刷到的朋友有所帮助,一起加油哦! 本章是继上篇 c++编程-基础 之后的 c++ 编程-核心. 生命就像一朵花,要拼尽 ...

  5. 基于.NetCore开发博客项目 StarBlog - (20) 图片显示优化

    前言 我的服务器带宽比较高,博客部署在上面访问的时候几乎没感觉有加载延迟,就没做图片这块的优化,不过最近有小伙伴说博客的图片加载比较慢,那就来把图片优化完善一下吧~ 目前有两个地方需要完善 图片瀑布流 ...

  6. apktool回编译报错

    报错 error: No resource identifier found for attribute 'XXX' in package 'XXX' 解决 将xml文件中 "http:// ...

  7. mingw编译opencv动态链接库和静态链接库及使用方法

    前言 我一直不知道编译的过程以及cmake, make 这些工具是干什么的,所有抽时间研究了一下. 简单来说就是 cmake 是根据 CMakeLists.txt 用来生成 makefile文件的.而 ...

  8. kettel

    下载教程:(目前最高版本7.1) 1.网址:https://community.hitachivantara.com/docs/DOC-1009855 2.

  9. GO开发工具litelDE的安装与使用

    1.MinGW的下载与安装 地址:http://sourceforge.net/projects/mingw/ 下载安装 D:\Program Files\MinGW 然后打开D:\Program F ...

  10. JavaScript入门①-基础知识筑基

    01.JavaScript基础知识 JavaScript(缩写:JS)是一种具有面向对象能力的.解释型的程序语言,基于对象和事件驱动,具有相对安全性的客户端脚本语言.JavaScript是一门完备的 ...