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_validvalidate的区别

当调用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 继承了GenericAPIViewViewSet,提供了基于模型的视图处理方法。可以通过继承ModelViewSet并定义对应的数据模型和序列化器来实现常见的数据操作,如获取列表、创建数据、获取单个数据、更新数据、部分更新数据和删除数据等。 list()create()retrieve()update()partial_update()destroy() 处理对数据模型的常见操作,可以快速地实现增删改查等功能
ReadOnlyModelViewSet 继承自GenericAPIViewViewSet,提供了只读操作的视图处理方法,包括list()retrieve()方法,用于获取数据模型的列表和单个数据。 list()retrieve() 处理只读数据操作,比如获取数据列表和单个数据等

ViewSet和ModelViewSet的区别

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

APIView和GenericAPIView的区别

类型 继承自 功能 使用场景
APIView View 只提供基本的请求处理方法,需要自己实现视图的功能 需要自己处理复杂的逻辑,或者需要调用其他的类来完成业务逻辑
GenericAPIView APIView 提供通用的方法和属性,例如 querysetserializer_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 基本认证 TokenAuthenticationSessionAuthentication
嵌套认证 MultiPartParserJSONParser
自定义认证 用户自定义认证类

自定义认证

定义自定义的认证类

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 许可协议。转载请注明来自 阿才的博客
微信打赏
支付宝打赏