Django REST Framework(简称DRF)是基于Django Web框架的一个开源的Web API框架。它提供了一组用于快速构建Web API的工具和库,包括序列化器、认证、权限、视图、路由和文档化等功能。
DRF的主要特点包括:
提供了强大的序列化器,可以将模型对象序列化为JSON等格式,并支持反序列化
提供了多种认证方式,包括基本认证、Token认证、OAuth认证等
提供了多种权限校验方式,包括基于角色的权限校验、基于对象的权限校验等
提供了多种视图类,包括基于函数的视图、基于类的视图、通用视图等
提供了路由功能,可以轻松地将URL映射到对应的视图
可扩展性,插件丰富
DRF官方:https://www.django-rest-framework.org/
GitHub:https://github.com/encode/django-rest-framework
DRF框架依赖于Django,需先安装Django环境。
pip install djangorestframework
在Django项目中使用DRF框架进行开发时,需要将rest_framework在INSTALLED_APPS中进行注册。
INSTALLED_APPS = [
'rest_framework',
]
字段 | 字段构造方式 | 描述 |
---|---|---|
BooleanField | BooleanField() | 布尔类型,通常用于表示真假数据 |
NullBooleanField | NullBooleanField() | 用于表示布尔类型的数据,可以包含三种值:True、False和Null。它可以自动将输入的字符串转换为布尔类型,并支持Null值 |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) | 字符串类型,通常用于表示文本数据 |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) | 电子邮件类型,通常用于表示电子邮件地址 |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) | 用于表示正则表达式类型的数据。它可以自动验证输入的字符串是否符合指定的正则表达式格式 |
SlugField | SlugField(max_length=50, minlength=None, allow_blank=False) | 是CharField的一个子类,通常用于表示URL中的短标识符。它可以自动将输入的字符串转换为URL安全的格式 |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) | URL类型,通常用于表示URL地址 |
UUIDField | UUIDField(format=‘hex_verbose’) hex_verbose、 hex、int、urn |
用于表示UUID(通用唯一识别码)类型的数据。它可以自动验证输入的字符串是否符合UUID格式,并将其转换为UUID对象 |
IPAddressField | IPAddressField(protocol=‘both’, unpack_ipv4=False, **options) | 用于表示IP地址类型的数据。它可以自动验证输入的字符串是否符合IP地址格式,并将其转换为IP地址对象 |
IntegerField | IntegerField(max_value=None, min_value=None) | 整数类型,通常用于表示数字数据 |
FloatField | FloatField(max_value=None, min_value=None) | 浮点数类型,通常用于表示小数数据 |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
高精度十进制数类型,通常用于表示货币等需要精确计算的数据 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) | 日期时间类型,通常用于表示时间戳等时间数据 |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) | 日期类型,通常用于表示日期数据 |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) | 时间类型,通常用于表示时间数据 |
DurationField | DurationField() | 用于表示时间间隔类型的数据,可以表示一段时间的长度。它可以自动将输入的字符串转换为时间间隔类型 |
ChoiceField | ChoiceField(choices) | 选择类型,可以定义一个选择列表,用于表示一组固定的选项 |
MultipleChoiceField | MultipleChoiceField(choices) | 用于表示多选框类型的数据。它可以定义一个选项列表,用于表示可选的选项 |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) | 文件类型,通常用于表示文件数据 |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) | 图像类型,通常用于表示图片数据 |
ListField | ListField(child=, min_length=None, max_length=None) | 列表类型,可以用于表示一个列表数据 |
DictField | DictField(child=) | 字典类型,可以用于表示一个字典数据 |
max_length和min_length是针对字符串类型的参数;max_value和min_value是针对数字类型的参数。
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_length | 最小长度 |
max_value | 最大值 |
min_value | 最小值 |
无论哪种字段类型都可以使用以下可选参数。
参数名称 | 说明 |
---|---|
read_only | 默认False 。用于指定字段是否只能用于序列化输出,不能用于反序列化输入。通常用于表示只读数据,例如时间戳等。在反序列化输入时,该字段的值会被忽略。 |
write_only | 默认False 。 用于指定字段是否只能用于反序列化,不能用于序列化输出。通常用于表示敏感数据,例如密码等。在序列化输出时,该字段的值会被忽略。 |
required | 表明该字段在反序列化时必须输入,默认True |
default | 序列化和反序列化时使用的默认值 |
error_messages | 包含错误编号与错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
allow_blank | 设置字段是否允许为空白字符串。如果设置为True,反序列化时如果该字段的值为空白字符串会被认为是有效值 |
validators | 设置字段的验证器。验证器是一个可调用对象,用于验证输入的数据是否符合要求。 |
定义序列化器类的字段时,如果没有指定read_only和write_only,则这两个参数默认值都为False,表明对应的字段既在序列化时使用,也在反序列化时使用
序列化器类的定义格式:
from rest_framework import serializers
class 序列化器类名(serializers.Serializer):
# 序列化器字段 = serializers.字段类型(选项参数)
新建serializers.py
文件保存某应用的序列化器类
from rest_framework import serializers
# 用户类
class User(object):
def __init__(self, name, age):
self.name = name
self.age = age
# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
序列化
if __name__ == '__main__':
# 创建User对象
user = User(name='test', age=22)
# 将user对象序列化为:{'name': 'test', 'age': 22}
serializer = UserSerializer(user)
# 获取序列化之后的数据
serializerData = serializer.data
print(serializerData)
反序列化与数据校验
if __name__ == '__main__':
data = {'name': 'test', 'age': 22}
# 对data的数据进行反序列化
serializer = UserSerializer(data=data)
# 调用is_valid进行数据校验,成功返回True,失败返回False
valid = serializer.is_valid()
print(valid)
# 获取校验失败之后的错误提示信息
errors = serializer.errors
print(errors)
# 获取校验通过之后的数据
user = serializer.validated_data
print(user)
Django初始化
编辑子应用下的tests.py文件,需要使用Django的东西,添加Django初始化代码
# 设置Django运行所依赖的环境变量
import os
from django.test import TestCase
from apps.user.models import User
from apps.user.serializers import UserSerializer
if not os.environ.get('DJANGO_SETTINGS_MODULE'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')
# 让Django进行一次初始化
import django
class User(models.Model):
name = models.CharField(max_length=6, unique=True, verbose_name='姓名')
age = models.IntegerField(default=0, verbose_name='年龄')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6)
age = serializers.IntegerField(label="年龄")
# 设置Django运行所依赖的环境变量
import os
from django.test import TestCase
from apps.user.models import User
from apps.user.serializers import UserSerializer
if not os.environ.get('DJANGO_SETTINGS_MODULE'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')
# 让Django进行一次初始化
import django
django.setup()
class MyTest(TestCase):
# 查询User
user = User.objects.get(id=1)
# 使用序列化器对象
serializer = UserSerializer(user)
# 获取序列化后的数据
data = serializer.data
print(data)
{'name': 'Django', 'age': 20}
当要被序列化的是包含多条数据的查询集QuerySet或list,可以通过添加many=True参数说明。
class MyTest(TestCase):
# 查询User
user = User.objects.all()
# 使用序列化器对象
serializer = UserSerializer(user, many=True)
# 获取序列化后的数据
data = serializer.data
print(data)
[OrderedDict([('name', 'Django'), ('age', 20)]), OrderedDict([('name', 'Python'), ('age', 30)])]
如果在序列化对象数据时,需要将其关联的对象一并序列化,则定义序列化器类的字段时,需要定义对应的关联对象嵌套序列化字段。对于关联字段,有3种定义方式。
如果一个对象关联的对象有多个,在序列化器类中定义嵌套序列化字段时,需要多添加一个
many=True
参数。
from django.db import models
# Create your models here.
class User(models.Model):
name = models.CharField(max_length=6, unique=True, verbose_name='姓名')
age = models.IntegerField(default=0, verbose_name='年龄')
class Meta:
db_table = 'tb_user'
verbose_name = '用户'
verbose_name_plural = verbose_name
class Car(models.Model):
TYPE_CHOICES = (
(0, '轿车'),
(1, 'SUV')
)
name = models.CharField(max_length=8, unique=True, verbose_name='名称')
price = models.DecimalField(max_digits=5, decimal_places=2, default=0, verbose_name='价格')
type = models.SmallIntegerField(choices=TYPE_CHOICES, verbose_name='类型')
user = models.ForeignKey(to=User, on_delete=models.CASCADE, verbose_name="用户")
class Meta:
db_table = 'tb_car'
verbose_name = '车辆'
verbose_name_plural = verbose_name
# 用户序列化器类:UserSerializer
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6)
age = serializers.IntegerField(label="年龄")
# 车辆序列化器类
class CarSerializer(serializers.Serializer):
TYPE_CHOICES = (
(0, 'male'),
(1, 'female')
)
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名字', max_length=8)
price = serializers.DecimalField(label='价格', max_digits=5, decimal_places=2, default=0)
type = serializers.ChoiceField(choices=TYPE_CHOICES, label='类型', required=False)
将关联对象序列化为关联对象的主键。指明字段时需要包含read_only=True或者queryset参数:
1.指定read_only=True参数时,该字段仅在序列化时使用。
car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', read_only=True,many=True)
class MyTest(TestCase):
# 查询User
user = User.objects.get(id=1)
# user对象序列化
serializer = UserSerializer(user)
# 获取序列化之后的数据
serializerData = serializer.data
print(serializerData)
{'name': 'Django', 'age': 22, 'car_set': [1, 2]}
2.指定queryset参数时,将被用作反序列化时参数校验使用。
#car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', read_only=True,many=True)
car_set = serializers.PrimaryKeyRelatedField(label='拥有车辆', queryset=Car.objects.all(),many=True)
{'name': 'Django', 'age': 22, 'car_set': [1, 2]}
使用指定的序列化器类将关联对象进行序列化。
class CarSerializer(serializers.Serializer):
TYPE_CHOICES = (
(0, 'male'),
(1, 'female')
)
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名字', max_length=8)
price = serializers.DecimalField(label='价格', max_digits=5, decimal_places=2, default=0)
type = serializers.ChoiceField(choices=TYPE_CHOICES, label='类型', required=False)
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6)
age = serializers.IntegerField(label="年龄")
car_set = CarSerializer(many=True)
{'name': 'Django', 'age': 22, 'car_set': [OrderedDict([('id', 1), ('name', '奥迪'), ('price', '99.00'), ('type', 1)]), OrderedDict([('id', 2), ('name', '宝马'), ('price', '88.00'), ('type', 2)])]}
将关联对象序列化为关联对象模型类__str__方法的返回值。
class Car(models.Model):
TYPE_CHOICES = (
(0, '轿车'),
(1, 'SUV')
)
name = models.CharField(max_length=8, unique=True, verbose_name='名称')
price = models.DecimalField(max_digits=5, decimal_places=2, default=0, verbose_name='价格')
type = models.SmallIntegerField(choices=TYPE_CHOICES, verbose_name='类型')
user = models.ForeignKey(to=User, on_delete=models.CASCADE, verbose_name="用户")
class Meta:
db_table = 'tb_car'
verbose_name = '车辆'
verbose_name_plural = verbose_name
def __str__(self):
return "name:%s price:%s" % (self.name, self.price)
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6)
age = serializers.IntegerField(label="年龄")
car_set = serializers.StringRelatedField(label='拥有车辆', many=True)
{'name': 'Django', 'age': 22, 'car_set': ['name:奥迪 price:99.00', 'name:宝马 price:88.00']}
数据校验可以调用is_valid()方法,会根据对应序列化类字段的类型以及一些选项参数对data中的数据进行校验。
调用is_valid进行数据校验时,除了一些基本的默认验证行为,还可以补充一些验证行为,有以下三种方法。
if __name__ == '__main__':
# User
user = {'name': 'test', 'age': 22}
# 创建序列化器对象,将{'name': 'test', 'age': 22}进行反序列化
serializer = UserSerializer(data=user)
# 数据校验:成功返回True,失败返回False
# 会根据对应序列化类字段的类型以及一些选项参数对data中的数据进行校验
valid = serializer.is_valid()
print(valid)
errors = serializer.errors
print(errors)
# 获取校验成功之后的数据
data = serializer.validated_data
print(data)
针对指定序列化器字段添加validators选项参数补充校验
def age_validator(value):
if value < 18:
raise serializers.ValidationError("未成年用户禁止操作")
# 用户序列化器类:UserSerializer。其可以针对User进行数据的序列化和反序列化操作
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6, )
age = serializers.IntegerField(label="年龄", validators=[age_validator])
if __name__ == '__main__':
# User
user = {'name': 'test', 'age': 17}
# 创建序列化器对象,将{'name': 'test', 'age': 22}进行反序列化
serializer = UserSerializer(data=user)
# 数据校验:成功返回True,失败返回False
valid = serializer.is_valid()
print(valid)
errors = serializer.errors
print(errors)
# 获取校验成功之后的数据
data = serializer.validated_data
print(data)
False
{'age': [ErrorDetail(string='未成年用户禁止操作', code='invalid')]}
{}
在序列化器类中定义特定方法
validate_
,针对特定字段进行补充验证
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6, )
age = serializers.IntegerField(label="年龄")
def validate_age(self, value):
if value < 18:
raise serializers.ValidationError("未成年用户禁止操作")
return value
if __name__ == '__main__':
# User
user = {'name': 'test', 'age': 17}
# 创建序列化器对象,将{'name': 'test', 'age': 22}进行反序列化
serializer = UserSerializer(data=user)
# 数据校验:成功返回True,失败返回False
valid = serializer.is_valid()
print(valid)
errors = serializer.errors
print(errors)
# 获取校验成功之后的数据
data = serializer.validated_data
print(data)
False
{'age': [ErrorDetail(string='未成年用户禁止操作', code='invalid')]}
{}
在序列化器类中定义validate方法针对多个字段的内容进行补充验证,
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6, )
age = serializers.IntegerField(label="年龄")
def validate(self, attrs):
age = attrs['age']
if age < 18:
raise serializers.ValidationError("未成年用户禁止操作")
return attrs
# 设置Django运行所依赖的环境变量
import os
from django.test import TestCase
from apps.user.models import User
from apps.user.serializers import UserSerializer
if not os.environ.get('DJANGO_SETTINGS_MODULE'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')
# 让Django进行一次初始化
import django
django.setup()
class MyTest(TestCase):
# User
user = {'name': 'test', 'age': 17}
# 创建序列化器对象,将{'name': 'test', 'age': 22}进行反序列化
serializer = UserSerializer(data=user)
# 数据校验:成功返回True,失败返回False
valid = serializer.is_valid()
print(valid)
errors = serializer.errors
print(errors)
1.在数据校验通过后,想基于validated_data完成数据对象的创建,可以通过序列化器对象.save()进行数据的保存。
2.在save方法内部会调用序列化器类的create或update方法,可以在create方法中实现数据新增,update方法中实现数据更新。
3.创建序列化器对象的时候,如果没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,则调用save()方法的时候,update()被调用。
# 用户序列化器类
class UserSerializer(serializers.Serializer):
name = serializers.CharField(label='姓名', max_length=6, )
age = serializers.IntegerField(label="年龄")
# 新建
def create(self, validated_data):
user = User.objects.create(**validated_data)
return user
# 更新,instance:更新的对象实例
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.age = validated_data.get('age', instance.age)
instance.save()
return instance
# 设置Django运行所依赖的环境变量
import os
from django.test import TestCase
from apps.user.models import User
from apps.user.serializers import UserSerializer
if not os.environ.get('DJANGO_SETTINGS_MODULE'):
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_demo.settings')
# 让Django进行一次初始化
import django
django.setup()
class MyTest(TestCase):
# 新增
user = {'name': 'Django', 'age': 22}
serializer = UserSerializer(data=user)
serializer.is_valid()
# 调用序列化器类的create方法,实现新增
serializer.save()
class MyTest(TestCase):
# 更新
user = User.objects.get(id=2)
data = {'name': 'Java', 'age': 20}
serializer = UserSerializer(user, data=data)
serializer.is_valid()
# 调用序列化器类的update方法,实现更新
serializer.save()
如果序列化器类对应Django某个模型类,则定义序列化器类时,可直接继承ModelSerializer。
ModelSerializer是Serializer类的子类,相对于Serializer,提供额外功能:
基于模型类字段自动生成序列化器类的字段
包含默认的create()和update()方法的实现
创建一个UserSerializer类
# 用户序列化器类
class UserSerializer(serializers.ModelSerializer):
class Meta:
# model:指明序列化器类对应的模型类
model = User
# fields:指明依据模型类的哪些字段生成序列化器类的字段,__all__表明包含所有字段
fields = '__all__'
执行python manage.py shell
命令,进入shell窗口,执行如下命令查看序列化器对象自动生成的具体字段
>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='姓名', max_length=6, validators=[<UniqueValidator(queryset=User.objects.all())>])
age = IntegerField(label='年龄', max_value=2147483647, min_value=-2147483648, required=False)
1.使用fields指明依据模型类的哪些字段生成序列化器类的字段,__all__表明包含所有字段,也可以指明具体哪些字段
class UserSerializer(serializers.ModelSerializer):
class Meta:
# model:指明序列化器类对应的模型类
model = User
# fields:指明依据模型类的哪些字段生成序列化器类的字段
fields = ('id', 'name')
执行quit()
退出shell,再执行python manage.py shell
命令,进入shell窗口,执行查看
>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='姓名', max_length=6, validators=[<UniqueValidator(queryset=User.objects.all())>])
2.使用exclude可以指明排除哪些字段
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
exclude = ('name',)
3.通过read_only_fields指明只读字段,即仅用于序列化的字段。
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'name', 'age')
read_only_fields = ('id', 'name')
可以使用extra_kwargs参数为自动生成的序列化器类字段添加或修改原有的选项参数。
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'name', 'age')
extra_kwargs = {
'name': {'max_length': 3, 'required': True},
'age': {'min_value': 18, 'required': True},
}
添加或修改原有的选项参数:
>>> from apps.users.serializers import UserSerializer, CarSerializer
>>> data = UserSerializer()
>>> data
UserSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='姓名', max_length=3, required=True, validators=[<UniqueValidator(queryset=User.objects.all())>])
age = IntegerField(label='年龄', max_value=2147483647, min_value=18, required=True)
re_path(r'^test/$', views.TestView.as_view(), name='test'),
from django.http import JsonResponse
from apps.users.models import User
from apps.users.serializers import UserSerializer
from django_redis.serializers import json
class TestView(View):
def get(self, request):
queryset = User.objects.all()
# 序列化
serializer = UserSerializer(queryset, many=True)
return JsonResponse(serializer.data, safe=False)
def post(self, request):
json_bytes = request.body
json_str = json_bytes.decode()
user_dict = json.loads(json_str)
# 反序列化-数据校验
serializer = UserSerializer(data=user_dict)
serializer.is_valid(raise_exception=True)
# 反序列化-数据保存
serializer.save()
return JsonResponse(serializer.data, status=201)
re_path(r'^test/(?P\d+)/$' , views.TestView.as_view(), name='test'),
class TestView(View):
def get(self, request, pk):
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
raise Http404
serializer = UserSerializer(user)
return JsonResponse(serializer.data)
def put(self, request, pk):
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return HttpResponse(status=404)
json_bytes = request.body
json_str = json_bytes.decode()
user_dict = json.loads(json_str)
# 反序列化-数据校验
serializer = UserSerializer(user, data=user_dict)
serializer.is_valid(raise_exception=True)
# 反序列化-数据保存
serializer.save()
return JsonResponse(serializer.data)
def delete(self, request, pk):
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return HttpResponse(status=404)
user.delete()
return HttpResponse(status=204)