简介
DRF(Django REST framework)是构建RESTful风格的Web api的强大而灵活的工具包。它是在Django框架基础之上,进行了二次开发。简称为DRF框架或REST framework框架。
特性
- 提供了强大的Serializer序列化器, 可以高效地进行序列化与反序列化操作
- 提供了极为丰富的类视图、Mixin扩展类、ViewSet视图集
- 提供了直观的Web API界面
- 多种身份认证和权限认证
- 强大的排序、过滤、分页、搜索、限流等功能
- 可扩展性,插件丰富
安装
pip install djangorestframework
将 rest_framework 添加到INSTALLED_APPS设置中:
INSTALLED_APPS = [
'rest_framework',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
序列化器的基本使用
序列化器 — Serializer
drf框架最大的特点就是它序列化器,其作用如下:
- 将模型对象序列化为字典,将来提供给视图经过response以后成为json字符串。
- 将客户端发送过来的数据经过视图调用request成为python字典,序列化器可以把字典转换成模型。
- 完成数据库校验和操作数据库功能
定义序列化器
继续使用前面已创建的学生表来演示序列化器的基本使用
from django.db import models
class Student(models.Model):
"""
学生表
"""
name = models.CharField('学生姓名', max_length=200, unique=True, help_text='学生姓名')
gender = models.SmallIntegerField('性别', default='1', help_text='性别')
hobby = models.CharField('爱好', max_length=200, null=True, blank=True, help_text='兴趣爱好')
age = models.IntegerField('年龄', null=True, )
create_time = models.DateTimeField('创建时间', auto_now_add=True, help_text='创建时间')
grade = models.ForeignKey('Grade', on_delete=models.SET_NULL, null=True, related_name='students') # 设置外键,级联删除)
class Meta:
"""
元数据,
"""
db_table = 'student' # 指定当前模型创建的表明,不写默认当前的模型名Student
verbose_name = '学生信息表' # 注释
verbose_name_plural = verbose_name # 指定为复数
在应用目录下创建serializers.py文件,定义类并继承rest_framework.serializers.Serializer,类似于模型,定义这个序列化器是为了序列化项目对象,所以字段与模型中的字段一一对应。
from rest_framework import serializers
class ProjectSerializer(serializers.Serializer):
"""
项目序列化器
"""
id = serializers.IntegerField(label='学生id', read_only=True) # 只读
name = serializers.CharField(label='学生姓名')
hobby = serializers.CharField(label='兴趣爱好',allow_null=True,required=False) # allow_null允许接收null,required=False实例化对象时可以忽略此字段
age = serializers.IntegerField(label='年龄')
c_time = serializers.DateTimeField(label='创建时间', read_only=True)
使用序列化器
一、序列化模型实例
In [12]: from projects.models import *
In [13]: from projects.serializers import ProjectSerializer
In [14]: s=Student.objects.first() # 实例化一个对象
In [15]: p = ProjectSerializers(s) # 通过序列化器转换为字典
In [16]: p.data
Out[17]: {'id': 3, 'name': 'test3', 'hobby': '玩游戏', 'age': 19}
为了完成序列化过程,还要将其转化为json,需要导入
Out[17]: from rest_framework.renderers import JSONRenderer
In [18]: JSONRenderer().render(p.data)
Out[18]: b'{"id":3,"name":"test3","hobby":"\xe7\x8e\xa9\xe6\xb8\xb8\xe6\x88\x8f","age":19}'
二、序列化查询集
使用序列化器时指定many参数等于True
In [22]: s1 = Student.objects.all()
In [23]: p1 = ProjectSerializers(s1)
In [25]: p1.data
In [26]: p1 = ProjectSerializers(s1,many=True)
In [27]: p1.data
Out[27]: [OrderedDict([('id', 3), ('name', 'test3'), ('hobby', '玩游戏'), ('age', 19)]), OrderedDict([('id', 4), ('name', '张三'), ('hobby', '玩'), ('age', 21)]), OrderedDict([('id', 5), ('name', 'zhaom'), ('hobby', 'play'), ('age',
112)]), OrderedDict([('id', 8), ('name', '阿三'), ('hobby', 'play'), ('age', 22)]), OrderedDict([('id', 9), ('name', 'test2'), ('hobby', 'wan'), ('age', 10)]), OrderedDict([('id', 13), ('name', 'ls'), ('hobby', None), ('age', 33)]),
OrderedDict([('id', 14), ('name', 'laa'), ('hobby', None), ('age', 35)]), OrderedDict([('id', 15), ('name', 'aa'), ('hobby', 'con'), ('age', 36)]), OrderedDict([('id', 16), ('name', 'ceaaa'), ('hobby', '11'), ('age', 1111)]), Ordered
Dict([('id', 17), ('name', '111'), ('hobby', ''), ('age', 222)]), OrderedDict([('id', 18), ('name', 'test33'), ('hobby', '打篮球'), ('age', 99)]), OrderedDict([('id', 21), ('name', 'test'), ('hobby', '打篮球'), ('age', 991)])]
In [28]: JSONRenderer().render(p1.data)
Out[28]: b'[{"id":3,"name":"test3","hobby":"\xe7\x8e\xa9\xe6\xb8\xb8\xe6\x88\x8f","age":19},{"id":4,"name":"\xe5\xbc\xa0\xe4\xb8\x89","hobby":"\xe7\x8e\xa9","age":21},{"id":5,"name":"zhaom","hobby":"play","age":112},{"id":8,"name":"\
xe9\x98\xbf\xe4\xb8\x89","hobby":"play","age":22},{"id":9,"name":"test2","hobby":"wan","age":10},{"id":13,"name":"ls","hobby":null,"age":33},{"id":14,"name":"laa","hobby":null,"age":35},{"id":15,"name":"aa","hobby":"con","age":36},{"
id":16,"name":"ceaaa","hobby":"11","age":1111},{"id":17,"name":"111","hobby":"","age":222},{"id":18,"name":"test33","hobby":"\xe6\x89\x93\xe7\xaf\xae\xe7\x90\x83","age":99},{"id":21,"name":"test","hobby":"\xe6\x89\x93\xe7\xaf\xae\xe7
\x90\x83","age":991}]'
反序列化
反序列化的过程与序列化类似,先将序列化数据(json)解析为原生python数据类型(省略),然后将其填充到一个序列化器对象中。
In [29]: data ={"name":"test111","hobby":"喝酒","age":44}
In [30]: p = ProjectSerializers(data=data)
In [31]: p.is_valid() # 校验
Out[32]: True
In [33]: s.validated_data # 校验后的数据
Out[34]: OrderedDict([('name', 'test111'), ('hobby', '喝酒'),
在调用save()方法之前,还需要实现两个方法来完成模型实例的创建和修改,在ProjectSerializer类中重写父类中的create与update方法:
from rest_framework import serializers
from project2s.models import Student
class ProjectSerializers(serializers.Serializer):
"""
项目序列化器
"""
id = serializers.IntegerField(label='学生id', read_only=True)
name = serializers.CharField(label='学生姓名')
hobby = serializers.CharField(label='兴趣爱好', allow_null=True, required=False) # 允许接收null,required=False实例化对象时可以忽略此字段
age = serializers.IntegerField(label='年龄')
c_time = serializers.DateTimeField(label='创建时间', read_only=True)
def create(self, validated_data):
return Student.objects.create(**validated_data) # 返回一个新对象
def update(self, instance, validated_data):
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
return instance
In [35]: s.save() # 序列化器实例可以调用save()直接返回一个模型实例
Out[36]: <Student: name:test111,hobby:喝酒>
当数据校验未通过时,可以通过errors查看具体信息:
举例 :
name字段不传,校验结果为False
In [9]: data ={"name":"","hobby":"喝酒","age":44}
In [10]: p1 = ProjectSerializers(data=data)
In [11]: p1.is_valid()
Out[11]: False
In [12]: p1.error_messages
Out[12]:
{'required': '该字段是必填项。',
'null': '该字段不能为 null。',
'invalid': '无效数据。期待为字典类型,得到的是 {datatype} 。'}
In [13]: p1.errors
Out[13]: {'name': [ErrorDetail(string='该字段不能为空。', code='blank')]}
模型序列化器
我们的ProjectSerializer类复制了大量Project模型中的的信息。RESTframework提供了一个ModelSerializer,它可以根据模型自动创建Serializer类,使代码更简洁。
from rest_framework import serializers
from project2s.models import Student
class ProjectSerializers(serializers.ModelSerializer):
class Meta:
model = Student # 指定模型
fields = ['id', 'name', 'hobby', 'age'] # 指定需要序列化的字段
可以通过打印序列化器实例的表示形式来检查它的所有字段:
In [1]: from project2s.serializers import *
In [2]: s = ProjectSerializers()
In [3]: s
Out[3]:
ProjectSerializers():
id = IntegerField(label='ID', read_only=True)
name = CharField(help_text='学生姓名', label='学生姓名', max_length=200, validators=[<UniqueValidator(queryset=Student.objects.all())>])
hobby = CharField(allow_blank=True, allow_null=True, help_text='兴趣爱好', label='爱好', max_length=200, required=False)
age = IntegerField(allow_null=True, label='年龄', max_value=2147483647, min_value=-2147483648, required=False)
ModelSerializer类只是创建serializer类的一个快捷方式,自动确定的字段,create()和update()方法的简单默认实现。