作用:提高RestAPI接口开发的效率
关键功能:
序列化器:序列化和反序列化
类视图,MiXin扩展类:简化视图代码的编写
安装: pip install djangorestframework
INSTALLED_APPS = [
...
'rest_framework', # 添加
]
序列化:将模型对象转换为字典或者json的过程,叫做序列化的过程。
反序列化:将客户端传递的数据保存转化到模型对象的过程,叫做反序列化的过程。
核心:
1. 将数据库数据序列化为前端所需要的格式,并返回;
2. 将前端发送的数据反序列化为模型类对象,并保存到数据库中。
DRF中的serializer就类似于Djano中的Form,只不过Form是针对模板的,而serializer是针对json,而且非常强大
功能:进行数据的序列化和反序列化
使用:首先定义序列化器类
序列化功能:将对象转换字典。
1.序列化单个对象(many=False)
2.序列化多个对象(many=True)
3.关联对象的嵌套序列化
反序列化功能:
数据校验:
1.基本验证
2.补充验证
数据保存
1.数据新增create
2.数据更新update
定义模型类:
class 模型类(modles.Model):
模型字段 = models.字段类型(选项参数)
定义序列化器类:
from rest_framework import serializers
class 序列化器类(serializers.Serializer):
序列化器字段= serializers.字段类型(选项参数)
序列化器类(instance=None,data={},**kwargs)
1.进行序列化操作,将对象传递给instance
2.进行反序列化操作,将数据传递给data
如果创建序列化器对象的时候,没有传递instance实例,create()被调用,
如果传递了instance实例,则调用save()方法的时候,update()被调用。
serializer = BookSerializer(data=data) # 没有传递instance实例,新建数据
serializer = BookSerializer(book,data=data) # 传进了instance参数,表示更新数据库
class User(object):
"""用户类"""
def __init__(self, name, age):
self.name = name
self.age = age
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
序列化:
# user = User(name="Monkey", age=18)
# res = UserSerializer(user) #序列化多个对象,需要添加many=True
# dict = res.data
反序列化:
# 假如现在客户端给服务器传递了两个参数:那name,age,利用这两个数据创建一个用户的对象,但是需要先进行数据校验
req_data = {
'name':"Moneky",
# "age":24
}
# 反序列化-数据校验
serializer = UserSerializer(data=req_data)
res = serializer.is_valid()
print(res)
print(serializer.errors) # 获取校验出错的信息
print(serializer.validated_data) # 获取校验之后的数据
serializer.save()保存数据(调用序列化类的create方法)
class 模型类(modles.Model):
模型字段 = models.字段类型(选项参数)
在定义序列化器类的字段时,write_only和read_only默认值为False,说明这个字段既在序列化时使用,也在反序列化时使用。
通用选项参数:
write_only: 设置为True,该字段只在序列化时使用,反序列化操作时不使用
read_only: 设置为True,该字段只在序列化时使用,反序列化时不使用
default:设置序列化和反序列化时所使用的默认值
requird:默认值是True,指明在进行反序化时此字段是否必须传入
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器,
eg:(验证是否唯一)validators=
[UniqueValidator(queryset=UserProfile.objects.all(), message='用户已存在')]
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息
style 控制浏览器如何渲染此字段,例如 'input_type' 和 'base_template'
3.主从表数据关联查询
PrimaryKeyRelatedField
StringRelatedField
SlugRelatedField
HyperlinkedRelatedField
HyperlinkedIdentityField
展示主表的详细信息
4.添加数据(create)
- 我们,想要添加数据,就需要在序列化器类中定义一个create()方法。
在这里,我们需要返回添加的数据给前端,因为我们定义的API是遵守RESTful设计风格的。
- 当我们创建序列化对象时,只传递data数据,就表示我们需要向数据库里添加数据。
所以,当序列化器对象调用save()方法时,会自动调用序列化器类中的create()方法。
例如:
def create(self, validated_data):
'''
序列化器进行新增数据的方法
:param validated_data: 通过验证的字典数据
:return:根据RESTful设计方式,需要将添加的数据返回
'''
return BookInfo.objects.create(**validated_data)
5.更新数据(update)
我们,想要修改数据时,需要在序列化器类中定义一个update()方法。
例如:
def update(self, instance, validated_data):
'''
序列化器进行修改数据的方法
:param instance: 需要修改的模型对象
:param validated_data: 前端传递的字典数据
:return: 根据RESTful设计方式,需要将修改的数据返回
'''
# 新值覆盖旧值
instance.字段名 = validated_data.get(字段名)
instance.title = validated_data.get('title')
instance.pub_date = validated_data.get('pub_date')
instance.read = validated_data.get('read')
instance.comment = validated_data.get('comment')
instance.save()
return instance
6.添加与更新实例
#在serializer中拿到user对象:user = self.context['request'].user
#用户进行加入购物车操作时,不是直接在数据库表中添加,需要判断该商品购物车中是否已存在
重写create,update方法
class ShopCartSerializer(serializers.Serializer):
user = serializers.HiddenField(default=CurrentUserDefault())
goods = serializers.PrimaryKeyRelatedField(required=True, queryset=Goods.objects.all())
nums = serializers.IntegerField(required=True, min_value=1, error_messages={
'required': '商品数量必须添加',
'min_value': '商品数量不能少于1'
})
def create(self, validated_data):
#在serializer中拿到user对象:user = self.context['request'].user
# goods: this.productId, // 商品id nums: this.buyNum, // 购买数量
goods = validated_data['goods']
nums = validated_data['nums']
user = self.context['request'].user
# 进行数据库的查询
shopcart = ShoppingCart.objects.filter(user=user, goods=goods)
if shopcart.exists():
# 原来在购物车中存在此商品
cart = shopcart.first()
cart.nums += nums
cart.save()
else:
# 购物车中此用户没有添加过此商品
cart = ShoppingCart.objects.create(user=user, goods=goods, nums=nums)
return cart
def update(self, instance, validated_data):
# instance shopcart对象
instance.nums = validated_data['nums']
instance.save()
return instance
validators来指明补充验证函数(验证是否唯一)
validators=
[UniqueValidator(queryset=UserProfile.objects.all(), message='用户已存在')]
validate_<fieldname>来针对特定字段进行补充验证class SmsSerializer(serializers.Serializer):
mobile = serializers.CharField(max_length=11)
def validate_mobile(self, mobile):
if UserProfile.objects.filter(mobile=mobile).exists():
raise serializers.ValidationError('此手机号码已注册')
if not re.match(REGEX, mobile):
raise serializers.ValidationError('手机号码格式错误')
return mobile
def validate_code(self, code):
#init_data 指的是最原始的没有经过验证的数据
#取前端传递过来的参数用self.initial['username']
verifyCodes = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by('-send_time')
def validate(self, attrs):
#在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:
# request、format、view,这三个数据对象可以在定义序列化器时使用
mobile = self.context['view'].kwargs['mobile']
def validate(self, attrs): # 全局验证 ['username','password','mobile']
'''
对多个字段进行验证
:param attrs: 前段传递的字典数据
:return: 验证成功:返回attrs;验证失败:返回错误信息
'''
attrs['mobile'] = attrs['username']
del attrs['code']
return attrs
是Serizalizer类的子类,在定义序列化器类时,如果序列化器类针对的是某个模型类,可以直接继承于ModelSerializer。
ModelSerializer同Serializer很相似,只不过建立了序列化类和Model类的强联系,简化了代码,提高了代码的可重用性。
好处:
- 基于模型类自动生成一系列字段
- 基于模型类自动为Serializer生成validators,比如unique_together
- 包含默认的create()和update()的实现
class BookSerializer(serializers.ModelSerializer):
# model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
# fields 指明该序列化器包含模型类中的哪些字段,'__all__'指明包含所有字段
class Meta:
model = BookInfo
fields = '__all__' # 返回给前端的json中包含的字段
__all__ 表名包含所有字段,也可以写明具体哪些字段 :class Meta:
model = HeroInfo
fields = '__all__'
fields = ('id', 'btitle', 'bpub_date')
class Meta:
model = HeroInfo
exclude = ('image',)
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
这里,我们需要注意的时extra_kwargs属性的值个格式是个字典。
class Meta:
model = Classes
fields = "__all__"
extra_kwargs = {
'bcomment':{
'min_value':0,
'max_value':99999
}
}
class BookSerializer2(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
class Meta:
model = UserFav
validators = [
UniqueTogetherValidator(
queryset=UserFav.objects.all(),
fields=('user', 'goods'),
message="已经收藏"
)
]
1.serializerMethodField
在我们开发的时候,我么使用序列化器序列化返回的时候,返回的大多都是数据框中一个表中的字段,但是我们还想返回一些其他表(关联表)中的字段数据或者数据库中没有的字段怎么办,或者说根据字段数据(true flase)来返回别的数据,此时怎么办哪,drf框架已经帮我们想好了,他就是serializerMethodField
标准写法就是get_名字,instance表示的是此时你model中的对象,可以根据此对象来查询关联的数据库中字段的数据,
class MessageListSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(read_only=True)
created_at = serializers.DateTimeField(read_only=True)
is_read = serializers.SerializerMethodField()
def get_is_read(self, obj):
#这里的obj是Serializer的Model经过查询后的结果集中的每个对象,也就是说,每查询到一个符合条件的纪录,该函数就会执行一次,向这个纪录中序列化这个函数字段
# return '已读' if obj['is_read'] else '未读'
return '已读' if obj.is_read else '未读'
class Meta:
model = Message
fields = ('id', 'title', 'created_at', 'is_read')`
2.HiddleField隐藏字段
不依靠输入,而需要设置默认的值,不需要用户自己post数据过来,也不会显式返回给用户,最常用的就是user!!
# 获取当前用户,并且隐藏了该字段,不会序列化返回给前端
user = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
原理:源码:提取request中的user,前端返回的token中会带上user信息
class CurrentUserDefault(object):
def set_context(self, serializer_field):
self.user = serializer_field.context['request'].user
def __call__(self):
return self.user
def __repr__(self):
return unicode_to_repr('%s()' % self.__class__.__name__)
带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request,如果有,就给图片加上域名,
比如说我们视图用的是apiview():
我们需要序列化数据的时候,加 context={"request":request}
在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,
TestSerilaizer(instance=instance, context={"request":request})
在序列化器里调用序列化器
goods_json = GoodsSerializer(good_ins, many=False, context={'request': self.context['request']}).data #注意具体语法
反序列化,反序列化是指从前端接收的json数据,转成数据对象的过程,更新操作、保存操作有反序列化操作,接收前端->验证数据->保存或更新为新的数据对象 序列化将获取到的数据对象转化为json数据。 如果使用上一篇的写法,反序列化和序列化都要自己进行写代码,为了提高效率,使用Django Rest Framework,把反序列化和序列化代码进行了封装,定义一个序列化器Serializer...
在笔者认为,在Django rest framework中最重要的是序列化组件,通过序列化我们可以将我们后台数据通过一定格式发送到我们的前端,然后通过一定的方法展示我们的数据。 那么我们就开始介绍我们的序列化组件吧! 自定义字段 url部分: 视图部分: 基本用法: 各种字段连接关系的使用: 深度控制以及反向生成UR...
解析器是对请求体数据进行解析 序列化有两个用处: 1.对 QuerySet进行序列化(json不能序列化QuerySet类型) 2.对请求数据进行校验 Django也自带了一个对QuerySet进行序列化的方法,后续补充 现在看REST framework的序列化: 基本使用(对 QuerySet进行序列化) 第一种实现方式 一,普通数据库 #数据库 #视图 二,带有可执行字段的数据库 #数据库表...
Django REST framework 序列化的使用 基本使用 1)先获取一个图书对象 2)创建序列化器实例 3)获取序列化的数据 4)如果要被序列化的数据是包含多条数据的查询集QuerySet,可以通过添加many=True参数来补充说明。 关联对象嵌套序列化 如果需要序列化的数据中包含其他关联对象,则对关联对象数据的序列化需要指明。 例如,在定义英雄数据的序列化器的时候,外键book(即所...
创建项目 我们需要创建一个项目(project)。 然后我们创建一个app,来构建简单的Web API。 我们需要将这个新建的 snippets app 和 rest_framework app 添加到 INSTALLED_APPS 中。编辑 tutorial/settings.py 文件: 好啦,我们准备开干了。 创建模型(model) 出于教程的设计考虑,我们将先创建一个简单的 Snippet...
serializers是什么?官网是这样的”Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other con...
Django REST framework教程——序列化 创建项目 已经准备就绪,开始学习序列化 创建models snippets/models.py 我们还需要为代码片段模型创建初始迁移,并首次同步数据库。 好了,先停一停 看一下 pygments 使用 Serializer 在snippets目录名serializers.py并添加以下内容 序列化测试 使用 Mode...
创建一个序列化类 使用序列化有四种方式 使用json模块,完全手写 使用django自带的序列化模块 1,# from django.core import serializers 2,# data=serializers.serialize(“json”,book_list) 使用REST framework 带的序列化方法,但是自己写规则&nbs...
APIView Serializer ModelSerializer APIView中使用dispatch 代码示例 APIView Serializer models url views 测试如下: http://127.0.0.1:8000/books/ ModelSerializer 经过测试效果一样 APIView中使用dispatch 需要使用原生的HttpResponse,如果使用Re...
模型:作者和新闻 序列化器 查询视图 响应数据 参考资料 django rest framework 嵌套序列化...