Django Rest Framework框架教程

当学习Django Rest Framework(DRF)时,以下是一个可能的目录:

DRF基础知识

了解DRF

DRF指的是Django Rest Framework,是一个开源的第三方库,它是基于Django框架的构建RESTful API的工具集。DRF提供了一组强大而灵活的工具,可以帮助开发人员更快地构建高质量的Web API,并提供基本的功能,如序列化、验证、认证、授权、过滤、搜索、分页、版本控制等。DRF还提供了可扩展性和灵活性,可以通过使用类和函数视图、路由和中间件等进行自定义。由于DRF是基于Django框架构建的,因此它可以轻松地集成到现有的Django应用程序中,并利用Django的许多优秀特性,如ORM、模型和管理界面等。

安装DRF

软件 版本
Python 3.8
Django 3.2.18
DRF 3.14.0

安装drf

pip3.8 install djangorestframework -i https://pypi.douban.com/simple

配置Django使用DRF框架

#编辑settings.py配置文件
INSTALLED_APPS = [
'rest_framework',
]

DRF序列化

API接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:序列化和反序列化

序列化和反序列化的区别

序列化可以理解为前端向Django请求数据,Django的模型对象数据无法直接让前端识别,所以需要将模型累对象数据序列化为Json数据返回给前端
反序列化也可以理解为前端向Django提交数据,但是该数据有部分Django无法识别或是需要将数据转换为其他类型;这时需要反序列化将数据进行转换

序列化器

序列化器的作用

序列化:序列化器会把模型对象转换成字典,经过response以后变成json字符串
反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型;完成数据校验功能

序列化器

定义序列化器

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名称', max_length=20)
bpub_date = serializers.DateField(label='发布日期', required=False)
bread = serializers.IntegerField(label='阅读量', required=False)
bcomment = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)

序列化器的使用

serializer.data #返回Json数据

反序列化

数据校验

使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,否则返回False。
验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的validated_data属性获取数据。
例如:

if serializer.is_vaild():
return serializer.data
else:
return serializer.error

数据校验三种方式

数据校验is_valid和validate的区别

当调用is_valid()方法时,DRF会自动执行验证规则,将验证结果存储在验证对象的errors属性中
validate()方法则提供了更高级别的验证逻辑。如果我们需要进行一些更加复杂的验证操作,可以通过重写validate()方法来实现。

validate_字段名数据校验

对字段进行验证,如:

class BookInfoSerializer(serializers.Serializer):
def validate_btitle(self, value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")
return value

validate数据校验

在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如

class BookInfoSerializer(serializers.Serializer):
def validate(self, attrs):
bread = attrs['bread']
bcomment = attrs['bcomment']
if bread < bcomment:
raise serializers.ValidationError('阅读量小于评论量')
return attrs

validators数据校验

在字段中添加validators选项参数,也可以补充验证行为;这种情况一般用来实现多个序列化器实现相同的数据校验方法,如:

def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")

class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])

保存数据

前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象。
可以通过实现create()和update()两个方法来实现:

class BookInfoSerializer(serializers.Serializer):
def create(self, validated_data):
"""新建"""
return BookInfo(**validated_data)

def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
instance.btitle = validated_data.get('btitle', instance.btitle)
instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
instance.bread = validated_data.get('bread', instance.bread)
instance.bcomment = validated_data.get('bcomment', instance.bcomment)
return instance

如果需要在返回数据对象的时候,也将数据保存到数据库中,则可以进行如下修改:

class BookInfoSerializer(serializers.Serializer):
def create(self, validated_data):
"""新建"""
return BookInfo.objects.create(**validated_data)

def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
instance.btitle = validated_data.get('btitle', instance.btitle)
instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
instance.bread = validated_data.get('bread', instance.bread)
instance.bcomment = validated_data.get('bcomment', instance.bcomment)
instance.save()
return instance

模型类序列化器

模型类序列化器和序列化器的区别

总结:模型类序列化器主要用于序列化Django模型类对象,而普通序列化器则用于序列化Python对象

特性 模型类序列化器 普通序列化器
应用场景 序列化Django模型类对象 序列化Python字典、列表、自定义对象等
需要定义的字段 模型类的字段 序列化器的字段
序列化方式 将模型类对象序列化为JSON等格式的数据 将Python对象序列化为JSON等格式的数据
反序列化方式 将JSON等格式的数据反序列化为模型类对象 将JSON等格式的数据反序列化为Python对象
相关概念 模型类、模型类字段、模型类关联关系、模型类管理器等 序列化器、字段、嵌套序列化器、序列化器关联关系等
常用方法 to_representation()、to_internal_value() to_representation()、to_internal_value()

使用所有字段

class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')

指定字段

class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')

排除某个字段

class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)

添加额外参数

class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
extra_kwargs = {
'bread': {'min_value': 0, 'required': True},
'bcomment': {'min_value': 0, 'required': True},
}

路由

对于视图集ViewSet和ModelViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息
REST framework提供了两个router:SimpleRouter和DefaultRouter

ViewSet和ModelViewSet

ViewSet和ModelViewSet使用动态路由案例:

from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'router_stu', StudentModelViewSet, base_name='student')

action

在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。例如:
下表描述了 action 装饰器中的参数及其描述:

参数名 描述
detail 指定 action 是否作用于单个对象的详情视图。默认值为 True,表示 action 作用于单个对象的详情视图,否则作用于集合视图。
methods 指定 action 支持的 HTTP 请求方法。默认值为 None,表示支持所有 HTTP 方法。可以是一个包含多个字符串的列表,例如 ['get', 'post']。
url_path 指定 action 的 URL 片段。如果未指定,则使用 action 的名称。
url_name 指定 action 的 URL 名称。如果未指定,则使用视图集的 URL 名称和 action 的名称。
serializer_class 指定 action 使用的序列化器类。如果未指定,则使用视图集的默认序列化器。
permission_classes 指定 action 使用的权限类。如果未指定,则使用视图集的默认权限类。
authentication_classes 指定 action 使用的认证类。如果未指定,则使用视图集的默认认证类。
throttle_classes 指定 action 使用的节流类。如果未指定,则使用视图集的默认节流类。

xxxxxxxxxx db2 deactivate db bash

类型 说明 常用方法 使用场景
APIView 基于函数的视图和基于类的视图之间的中间层,提供了一些常用的HTTP请求处理方法,如get()、post()、put()等 get()、post()、put()、delete()等 处理基本HTTP请求,处理逻辑简单
ViewSet 基于类的视图,提供了多个请求处理方法,如list()、create()、retrieve()、update()、partial_update()和destroy()等,用于处理对数据模型的各种操作,如获取列表、创建数据、获取单个数据、更新数据、部分更新数据和删除数据等。 list()、create()、retrieve()、update()、partial_update()和destroy()等 处理对数据模型的常见操作,比如获取数据列表、创建数据、获取单个数据、更新数据、部分更新数据和删除数据等
GenericAPIView 是APIView的子类,提供了一些通用的处理方法,如分页、过滤、排序等。通过继承GenericAPIView和相应的Mixin类,可以快速地实现常用的数据操作视图。 get()、post()、put()、delete()等 实现一些通用的数据处理逻辑,如分页、过滤、排序等
ModelViewSet 继承了GenericAPIView和ViewSet,提供了基于模型的视图处理方法。可以通过继承ModelViewSet并定义对应的数据模型和序列化器来实现常见的数据操作,如获取列表、创建数据、获取单个数据、更新数据、部分更新数据和删除数据等。 list()、create()、retrieve()、update()、partial_update()和destroy()等 处理对数据模型的常见操作,可以快速地实现增删改查等功能
ReadOnlyModelViewSet 继承自GenericAPIView和ViewSet,提供了只读操作的视图处理方法,包括list()和retrieve()方法,用于获取数据模型的列表和单个数据。 list()、retrieve()等 处理只读数据操作,比如获取数据列表和单个数据等

ViewSet和ModelViewSet的区别

类型 继承自 功能 使用场景
ViewSet APIView 只提供基本的请求处理方法,需要自己实现视图的功能 需要自己处理复杂的逻辑,或者需要调用其他的类来完成业务逻辑
ModelViewSet GenericAPIView 提供通用的方法和属性,自动处理常见的增删改查操作,自动创建基于模型的序列化器和反序列化器 与 Django 中的模型打交道,完成视图的 CRUD 操作

APIView和GenericAPIView的区别

类型 继承自 功能 使用场景
APIView View 只提供基本的请求处理方法,需要自己实现视图的功能 需要自己处理复杂的逻辑,或者需要调用其他的类来完成业务逻辑
GenericAPIView APIView 提供通用的方法和属性,例如 queryset、serializer_class 等,可以方便地完成视图的 CRUD 操作,也提供了自动创建基于模型的序列化器和反序列化器的功能 与 Django 中的模型打交道,完成视图的 CRUD 操作

APIView

APIView 是 DRF 中最基本的视图类,需要手动处理 HTTP 请求和响应。例如:

from rest_framework.views import APIView
from rest_framework.response import Response

class HelloWorldView(APIView):
def get(self, request):
return Response({"message": "Hello, world!"})

GenericAPIView

GenericAPIView 是 DRF 中常用的视图类之一,提供了许多通用的方法和属性,例如 queryset、serializer_class 等,可以方便地完成视图的 CRUD 操作

from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer

class BookView(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer

ViewSet

ViewSet 是 DRF 中常用的视图类之一,需要手动处理 HTTP 请求和响应,但是可以将多个相关的操作封装在同一个类中,适用于处理一个资源的多个不同的操作

from rest_framework.views import Response
from rest_framework.viewsets import ViewSet

class HelloViewSet(ViewSet):
def list(self, request):
return Response({"message": "Hello, world!"})

def create(self, request):
# 创建对象的逻辑
pass

def retrieve(self, request, pk=None):
# 获取对象的逻辑
pass

def update(self, request, pk=None):
# 更新对象的逻辑
pass

def partial_update(self, request, pk=None):
# 部分更新对象的逻辑
pass

def destroy(self, request, pk=None):
# 删除对象的逻辑
pass

ModelViewSet

ModelViewSet 是 DRF 中最常用的视图类之一,可以自动处理常见的增删改查操作,自动创建基于模型的序列化器和反序列化器。例如:

from rest_framework.viewsets import ModelViewSet
from .models import Book
from .serializers import BookSerializer

class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class =

认证

DRF认证的作用

使用 DRF 认证,可以保证用户的身份得到有效验证,从而提升系统的安全性和可靠性。同时,DRF 认证还可以减少开发者的工作量,提高开发效率

DRF提供的认证

以下是 DRF 认证提供的主要功能以及对应的认证方式:

功能 认证方式
基于 Token 的认证 TokenAuthentication
基于 Session 的认证 SessionAuthentication
基于 OAuth2 的认证 OAuth2Authentication
基于 JSON Web Token(JWT)的认证 JSONWebTokenAuthentication
HTTP 基本认证 BasicAuthentication
高级 HTTP 基本认证 TokenAuthentication 和 SessionAuthentication
嵌套认证 MultiPartParser 和 JSONParser
自定义认证 用户自定义认证类

自定义认证

定义自定义的认证类

from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework.exceptions import AuthenticationFailed
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _

User = get_user_model()

class TokenAuthentication(BaseAuthentication):
keyword = 'Token'

def authenticate(self, request):
auth_header = get_authorization_header(request).split()
if not auth_header:
return None
if auth_header[0].decode() != self.keyword:
return None
if len(auth_header) == 1:
raise AuthenticationFailed(_('Invalid token header. No credentials provided.'))
if len(auth_header) > 2:
raise AuthenticationFailed(_('Invalid token header. Token string should not contain spaces.'))
token = auth_header[1].decode()
try:
user = User.objects.get(token=token)
except User.DoesNotExist:
raise AuthenticationFailed(_('Invalid token.'))
return (user, token)

def authenticate_header(self, request):
return self.keyword

在django settings.py配置文件中指定使用的认证类

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'path.to.TokenAuthentication',
],
}

Token认证

DRF提供了Token认证类,可以使用Token进行认证,使用方法如下:
首先在settings.py中添加Token认证类

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
}

在需要进行认证的视图中添加Token认证
参数描述:

参数名 描述
authentication_classes 指定用于身份验证的类列表。设置为TokenAuthentication,表示使用Token进行身份验证。
permission_classes 指定用于授权的类列表。设置为IsAuthenticated,表示只有认证用户才有访问权限。
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response

class MyView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]

def get(self, request, format=None):
content = {
'user': str(request.user), # `django.contrib.auth.User` instance.
'auth': str(request.auth), # None
}
return Response(content)

客户端使用Token进行认证

在使用Token进行认证时,需要先创建一个Token,然后在请求头中添加Authorization: Token <token>。

from rest_framework.authtoken.models import Token
import requests

# 创建Token
user = User.objects.get(username='username')
token = Token.objects.create(user=user)

# 使用Token进行认证
response = requests.get('http://localhost:8000/my-view/', headers={'Authorization': f'Token {token.key}'})

Session认证

实现基于session的认证可以使用SessionAuthentication类,它是Django内置的一种认证方式。
在DRF中使用基于session的认证方式,可以将authentication_classes设置为SessionAuthentication,并且将permission_classes设置为IsAuthenticated,表示只有经过身份验证的用户才有访问权限。

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class MyView(APIView):
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]

def get(self, request):
# 处理GET请求的代码
pass

def post(self, request):
# 处理POST请求的代码
pass

权限

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问,在执行视图的as_view()方法的dispatch()方法前,会先进行视图访问权限的判断

认证和权限的区别

认证(Authentication) 权限(Permission)
验证用户身份的过程 限制用户访问API的能力
通常包括用户名和密码的验证 限制用户在特定条件下执行特定操作的能力
用于验证请求是否来自已经登录的用户 用于限制哪些用户可以访问API以及哪些用户可以执行哪些操作
与用户身份验证相关 与用户访问权限相关
通常与权限结合使用,以确保API的安全性和保护用户数据的隐私 通常与认证结合使用,以确保API的安全性和保护用户数据的隐私

内置权限

DRF提供以下内置权限供用户使用:

权限类别 描述
AllowAny 允许所有用户访问
IsAuthenticated 仅允许已认证的用户访问
IsAdminUser 仅允许管理员用户访问
IsAuthenticatedOrReadOnly 已认证的用户可以执行任何操作,未认证的用户只能读取
DjangoModelPermissions 仅允许有关对象的权限的用户执行操作
DjangoModelPermissionsOrAnonReadOnly 仅允许有关对象的权限的用户执行操作,未认证的用户只能读取
DjangoObjectPermissions 仅允许具有特定对象权限的用户执行操作
DjangoObjectPermissionsOrAnonReadOnly 仅允许具有特定对象权限的用户执行操作,未认证的用户只能读取

配置使用权限

全局使用权限

可以在配置文件settings.py中全局设置默认的权限管理类,如:

# drf的配置信息,需要卸载django的配置文件,而且必须写在REST_FRAMEWORK的字典中,才能被drf识别
REST_FRAMEWORK = {
....
# 权限[全局配置,所有的视图都会被影响到]
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', # 已经登录认证的用户才能访问
)
}

如果未指明,则采用如下默认配置:

'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)

局部视图使用权限

在具体的视图中通过permission_classes属性来设置,如:

from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class ExampleView(APIView):
permission_classes = (IsAuthenticated,)

自定义权限使用

如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部:

方法名 描述
has_permission 用于对视图级别的权限进行控制。根据请求判断是否有权限访问视图。
has_object_permission 用于对对象级别的权限进行控制。根据请求和特定对象判断是否有权限访问对象。

使用案例

定义自定义类

from rest_framework.permissions import BasePermission

class IsXiaoMingPermission(BasePermission):
def has_permission(self, request, view):
if request.user and request.user.username == "xiaoming":
return True

视图使用自定义类

from .permissions import IsXiaoMingPermission
class StudentViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
permission_classes = [IsXiaoMingPermission]

基于角色和权限的授权

在DRF中,基于角色和权限的授权是一种常见的权限控制机制。它通过将用户的角色和权限进行关联,来限制用户对API的访问和操作。
通常,基于角色和权限的授权包括以下几个步骤:

定义角色和权限

定义角色:按角色定义,用户可分为:管理员用户和普通用户
定义权限:创建、更新、删除、查看用户权限

关联角色和权限

管理员权限关联:创建、更新、删除、查看用户权限
普通用户权限关联:查看用户权限

用户角色分配

用户角色分配:用户1:管理员;用户2:普通用户

权限验证

自定义权限类:

from rest_framework.permissions import BasePermission

class CustomPermission(BasePermission):
def has_permission(self, request, view):
# 检查用户角色和权限
if request.user.role == 'admin':
return True # 管理员角色拥有所有权限
elif request.user.role == 'user':
# 检查请求方法和相应权限
if request.method == 'GET' and view.action == 'list':
return True # 普通用户角色只能查看用户
return False

限流

在DRF中,限流是一种用于控制API请求频率的机制,以防止滥用或过度使用API资源。DRF提供了多种限流策略,可以根据需要选择适合的限流方式。
DRF中的限流可以在全局范围或视图级别进行配置。
在DRF中通过使用DEFAULT_THROTTLE_CLASSES指定限流类;DEFAULT_THROTTLE_RATES指定限流速率,比如:1/s 表示每秒一个请求

限流类 描述
rest_framework.throttling.AnonRateThrottle 表示匿名用户限流
rest_framework.throttling.UserRateThrottle 表示用户级别的限流
rest_framework.throttling.ScopedRateThrottle 基于自定义作用域的限流

全局限流配置

使用DEFAULT_THROTTLE_RATES指定了每个限流类的速率,其中anon表示匿名用户的速率为100次/天,user表示用户的速率为1000次/小时

# settings.py

# 全局限流配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/hour',
}
}

局部限流配置

在视图集(MyViewSet)中进行了局部限流配置。通过设置throttle_classes属性,我们指定了两个限流类:AnonRateThrottle和UserRateThrottle,用于该视图集的限流。使用throttle_rates属性指定了每个限流类的速率,其中500/day表示匿名用户的速率为500次/天,50/hour表示用户的速率为50次/小时

from rest_framework.throttling import AnonRateThrottle, UserRateThrottle

class MyViewSet(viewsets.ModelViewSet):
throttle_classes = []
throttle_rates = []

def get_throttles(self):
throttle_classes = []
throttle_rates = []

if self.request.user.is_anonymous:
throttle_classes = [AnonRateThrottle]
throttle_rates = ['500/day']
else:
throttle_classes = [UserRateThrottle]
throttle_rates = ['50/hour']

return [throttle() for throttle in throttle_classes], throttle_rates

# 其他视图方法...

数据过滤

在DRF中,数据过滤是指根据特定条件对API返回的数据进行筛选和过滤。DRF提供了多种方式来进行数据过滤,包括查询字符串参数、过滤器类、自定义过滤器等。

查询字符串参数

当使用查询字符串参数进行数据过滤时,可以通过重写视图类的get_queryset方法来根据查询字符串参数对查询集进行筛选。例如:
重写get_queryset方法

from rest_framework import generics
from django.contrib.auth.models import User

class UserListAPIView(generics.ListAPIView):
serializer_class = UserSerializer

def get_queryset(self):
queryset = User.objects.all()

# 获取查询字符串参数
username = self.request.query_params.get('username')
email = self.request.query_params.get('email')

# 根据查询字符串参数进行过滤
if username:
queryset = queryset.filter(username=username)
if email:
queryset = queryset.filter(email=email)

return queryset

如果我们向以下URL发送请求:GET /api/users?username=john,返回以下数据:

[
{
"id": 1,
"username": "john",
"email": "john@example.com"
}
]

过滤器类

首先定义了一个过滤器类UserFilter,它继承自filters.FilterSet。在过滤器类中,我们定义了两个过滤字段username和email,并指定了它们的查询条件(lookup_expr)。这里使用的是icontains,表示不区分大小写的包含匹配。

from django_filters import rest_framework as filters

class UserFilter(filters.FilterSet):
username = filters.CharFilter(lookup_expr='icontains')
email = filters.CharFilter(lookup_expr='icontains')

class Meta:
model = User
fields = ['username', 'email']

然后,我们在UserListAPIView中设置了filter_backends属性为[filters.DjangoFilterBackend],表示启用了过滤器类。同时,将filterset_class属性设置为UserFilter,以指定使用我们定义的过滤器类。

class UserListAPIView(generics.ListAPIView):
serializer_class = UserSerializer
queryset = User.objects.all()
filter_backends = [filters.DjangoFilterBackend]
filterset_class = UserFilter

现在,我们可以向API视图发送请求,并使用查询字符串参数来进行数据过滤。例如,可以发送以下请求:

request
GET /api/users?username=john&email=example.com

自定义过滤器

创建了一个自定义过滤器类PriceRangeFilter,它实现了一个名为filter的方法。在该方法中,我们接收到的queryset参数是API视图的查询集,value参数是传递给过滤器的值。
假设过滤器的值是一个由连字符分隔的价格范围字符串,例如10-50。我们通过解析该字符串,将其分割为最小价格和最大价格,并使用price__range查询条件对查询集进行过滤。

class PriceRangeFilter:
def filter(self, queryset, value):
min_price, max_price = map(float, value.split('-'))
return queryset.filter(price__range=(min_price, max_price))

然后,我们在ProductListAPIView视图中设置了filter_backends属性,将PriceRangeFilter添加为过滤器后端。这样,当请求到达该视图时,将自动应用自定义过滤器类的过滤逻辑。

class ProductListAPIView(generics.ListAPIView):
serializer_class = ProductSerializer
queryset = Product.objects.all()
filter_backends = [PriceRangeFilter]

排序

在DRF(Django REST framework)中,可以使用排序功能对API的响应数据进行排序。DRF提供了多种排序选项和配置方式,使得排序变得非常灵活和易于使用。

排序可以在视图级别或全局级别进行配置。

全局配置排序

在DRF的设置文件(通常是settings.py)中,可以使用DEFAULT_FILTER_BACKENDS设置来配置默认的过滤器后端。可以将’rest_framework.filters.OrderingFilter’添加到该设置中,以启用全局级别的排序功能。

# settings.py

REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'rest_framework.filters.OrderingFilter',
],
}

通过字符串参数请求API,会自动进行排序:GET /api/products?ordering=name,price

视图配置局部排序

在视图级别,可以通过设置ordering属性来指定默认的排序字段。该属性可以是一个字符串或字符串列表,用于指定要应用的排序字段。如果指定了多个字段,数据将首先按照第一个字段排序,然后再按照后续字段进行排序。

from rest_framework import generics
from .models import Product
from .serializers import ProductSerializer

class ProductListAPIView(generics.ListAPIView):
serializer_class = ProductSerializer
queryset = Product.objects.all()
ordering = ['price']

根据请求的查询字符串参数来动态指定排序字段。可以通过在视图类中定义ordering_fields属性来限制可用的排序字段列表,以防止不受控制的排序参数。

from rest_framework import generics
from .models import Product
from .serializers import ProductSerializer

class ProductListAPIView(generics.ListAPIView):
serializer_class = ProductSerializer
queryset = Product.objects.all()
ordering_fields = ['price', 'name']

API请求字符串,如下:GET /api/products?ordering=price

分页

在DRF(Django REST framework)中,分页用于将大量数据分割成较小的页面,以提高 API 的性能和用户体验。DRF 提供了丰富的分页功能,可根据需求进行配置和定制。
以下是常用的分页类属性和方法:

属性/方法 描述
page_size 每页的数据数量,默认为 None(不分页)
page_query_param 用于指定页码的查询字符串参数名称,默认为 'page'
page_size_query_param 用于指定每页数据数量的查询字符串参数名称,默认为 'page_size'
max_page_size 允许的最大每页数据数量,默认为 None
paginate_queryset(queryset, request, view=None) 实现分页逻辑的方法
get_paginated_response(data) 返回分页后的响应的方法

默认分页类使用

启用分页功能,可以在视图中设置 pagination_class 属性为所需的分页类;可以通过url请求?page=2&size=20实现分页

class StudentListView(APIView):
pagination_class = PageNumberPagination

def get(self, request, format=None):
page_number = request.GET.get('page', 1)
page_size = request.GET.get('size', 10)

queryset = Student.objects.all()
paginator = self.pagination_class()
paginated_queryset = paginator.paginate_queryset(queryset, request)

# 在这里可以使用分页后的查询结果进行进一步操作,如序列化、返回响应等
# 其他视图代码...

自定义分页类

自定义分页类需要继承自 DRF 的 BasePagination 类,并实现相应的方法。paginate_queryset 方法用于实现分页逻辑,例如根据请求的页码和每页数据数量对查询集进行切片;get_paginated_response 方法用于返回分页后的响应,可以自定义响应的结构和格式。
例如:

from rest_framework.pagination import BasePagination

class MyPagination(BasePagination):
def paginate_queryset(self, queryset, request, view=None):
# 自定义实现分页逻辑
pass

def get_paginated_response(self, data):
# 自定义实现返回分页后的响应
pass

文件上传

在settings.py文件中添加以下配置,示例使用本地文件系统进行存储:

# settings.py
#表示本地存储路径
MEDIA_ROOT = 'uploads/'
#表示API请求路径
MEDIA_URL = '/media/'

创建一个序列化器类,继承自DRF的serializers.Serializer或serializers.ModelSerializer。定义一个file字段用于接收上传的文件

# serializers.py
from rest_framework import serializers

class FileUploadSerializer(serializers.Serializer):
file = serializers.FileField()

创建一个视图类,继承自DRF的视图类,例如APIView或ViewSet。在该视图类中定义处理文件上传的方法,如post方法。

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response

class FileUploadView(APIView):
def post(self, request, format=None):
serializer = FileUploadSerializer(data=request.data)
if serializer.is_valid():
file = serializer.validated_data['file']
# 处理上传的文件,例如保存到本地文件系统或云存储服务
# ...

return Response({'message': 'File uploaded successfully.'})
else:
return Response(serializer.errors, status=400)

在URL路由中定义相应的URL模式,将请求映射到对应的视图处理函数。

# urls.py
from django.urls import path
from .views import FileUploadView

urlpatterns = [
path('upload/', FileUploadView.as_view(), name='file-upload'),
]

使用第三方包和扩展

扩展包 功能
drf-yasg 自动生成API文档,支持Swagger和OpenAPI规范
drf-jwt 提供JSON Web Token(JWT)认证支持
django-filter 提供数据过滤功能,用于筛选和过滤API返回的数据
django-cors-headers 处理跨域资源共享(CORS)请求
drf-extensions 提供额外的功能和工具,如视图集扩展、嵌套路由等
django-rest-knox 提供Token认证支持,并改进了DRF的Token认证方式
djangorestframework-jwt 提供JWT认证支持,兼容DRF的Token认证方式
django-rest-auth 提供身份验证和用户管理功能,包括注册、登录、重置密码等
drf-nested-routers 支持嵌套路由,处理复杂的API关系和嵌套资源
django-oauth-toolkit 提供OAuth 2.0认证支持,构建OAuth 2.0授权服务器

使用Swagger生成API文档

安装Swagger相关的依赖:在你的Django项目中,使用pip安装以下依赖项:

pip install drf-yasg

在项目的设置文件中进行配置:打开项目的settings.py文件,将以下内容添加到文件末尾:

INSTALLED_APPS = [
...
'drf_yasg',
]

SWAGGER_SETTINGS = {
'DEFAULT_INFO': 'your_project_name.urls.swagger_info', # 指定Swagger文档的信息
}

创建Swagger文档信息:在你的项目中创建一个名为urls.py的文件(如果不存在),并在其中添加以下内容:

from django.urls import path
from rest_framework import permissions
from drf_yasg import openapi
from drf_yasg.views import get_schema_view

schema_view = get_schema_view(
openapi.Info(
title='Your API',
default_version='v1',
description='API documentation',
terms_of_service='https://www.example.com/terms/',
contact=openapi.Contact(email='contact@example.com'),
license=openapi.License(name='BSD License'),
),
public=True,
permission_classes=(permissions.AllowAny,),
)

swagger_info = 'your_project_name.urls.swagger_info' # 替换为你自己的项目路径
urlpatterns = [
...
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

在浏览器中访问:
http://localhost:8000/swagger/
http://localhost:8000/redoc/

文章作者: 慕容峻才
文章链接: https://www.acaiblog.top/Django Rest Framework框架教程/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿才的博客!
微信打赏
支付宝打赏