当学习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配置文件 |
DRF序列化
API接口开发,最核心最常见的一个过程就是序列化,所谓序列化就是把数据转换格式,序列化可以分两个阶段:序列化和反序列化
序列化和反序列化的区别
序列化可以理解为前端向Django请求数据,Django的模型对象数据无法直接让前端识别,所以需要将模型累对象数据序列化为Json数据返回给前端
反序列化也可以理解为前端向Django提交数据,但是该数据有部分Django无法识别或是需要将数据转换为其他类型;这时需要反序列化将数据进行转换
序列化器
序列化器的作用
序列化:序列化器会把模型对象转换成字典,经过response以后变成json字符串
反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型;完成数据校验功能
序列化器
定义序列化器
class BookInfoSerializer(serializers.Serializer): |
序列化器的使用
serializer.data #返回Json数据 |
反序列化
数据校验
使用序列化器进行反序列化时,需要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()
方法进行验证,验证成功返回True,否则返回False。
验证失败,可以通过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。
如果是非字段错误,可以通过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,可以通过序列化器对象的validated_data属性获取数据。
例如:
if serializer.is_vaild(): |
数据校验三种方式
数据校验
is_valid
和validate
的区别
当调用is_valid()方法时,DRF会自动执行验证规则,将验证结果存储在验证对象的errors属性中
validate()方法则提供了更高级别的验证逻辑。如果我们需要进行一些更加复杂的验证操作,可以通过重写validate()方法来实现。
validate_字段名数据校验
对
class BookInfoSerializer(serializers.Serializer): |
validate数据校验
在序列化器中需要同时对多个字段进行比较验证时,可以定义validate方法来验证,如
class BookInfoSerializer(serializers.Serializer): |
validators数据校验
在字段中添加validators选项参数,也可以补充验证行为;这种情况一般用来实现多个序列化器实现相同的数据校验方法,如:
def about_django(value): |
保存数据
前面的验证数据成功后,我们可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象。
可以通过实现create()和update()两个方法来实现:
class BookInfoSerializer(serializers.Serializer): |
如果需要在返回数据对象的时候,也将数据保存到数据库中,则可以进行如下修改:
class BookInfoSerializer(serializers.Serializer): |
模型类序列化器
模型类序列化器和序列化器的区别
总结:模型类序列化器主要用于序列化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 BookInfoSerializer(serializers.ModelSerializer): |
排除某个字段
class BookInfoSerializer(serializers.ModelSerializer): |
添加额外参数
class BookInfoSerializer(serializers.ModelSerializer): |
路由
对于视图集ViewSet和ModelViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息
REST framework提供了两个router:SimpleRouter和DefaultRouter
ViewSet和ModelViewSet
ViewSet和ModelViewSet使用动态路由案例:
from rest_framework import routers |
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 |
GenericAPIView
GenericAPIView 是 DRF 中常用的视图类之一,提供了许多通用的方法和属性,例如 queryset、serializer_class 等,可以方便地完成视图的 CRUD 操作
from rest_framework.generics import GenericAPIView |
ViewSet
ViewSet 是 DRF 中常用的视图类之一,需要手动处理 HTTP 请求和响应,但是可以将多个相关的操作封装在同一个类中,适用于处理一个资源的多个不同的操作
from rest_framework.views import Response |
ModelViewSet
ModelViewSet 是 DRF 中最常用的视图类之一,可以自动处理常见的增删改查操作,自动创建基于模型的序列化器和反序列化器。例如:
from rest_framework.viewsets import ModelViewSet |
认证
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 |
在django settings.py配置文件中指定使用的认证类
REST_FRAMEWORK = { |
Token认证
DRF提供了Token认证类,可以使用Token进行认证,使用方法如下:
首先在settings.py中添加Token认证类
REST_FRAMEWORK = { |
在需要进行认证的视图中添加Token认证
参数描述:
参数名 | 描述 |
---|---|
authentication_classes |
指定用于身份验证的类列表。设置为TokenAuthentication ,表示使用Token进行身份验证。 |
permission_classes |
指定用于授权的类列表。设置为IsAuthenticated ,表示只有认证用户才有访问权限。 |
from rest_framework.authentication import TokenAuthentication |
客户端使用Token进行认证
在使用Token进行认证时,需要先创建一个Token,然后在请求头中添加Authorization: Token <token>
。
from rest_framework.authtoken.models import Token |
Session认证
实现基于session的认证可以使用SessionAuthentication
类,它是Django内置的一种认证方式。
在DRF中使用基于session的认证方式,可以将authentication_classes
设置为SessionAuthentication
,并且将permission_classes
设置为IsAuthenticated
,表示只有经过身份验证的用户才有访问权限。
from rest_framework.authentication import SessionAuthentication |
权限
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问,在执行视图的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识别 |
如果未指明,则采用如下默认配置:
'DEFAULT_PERMISSION_CLASSES': ( |
局部视图使用权限
在具体的视图中通过permission_classes属性来设置,如:
from rest_framework.permissions import IsAuthenticated |
自定义权限使用
如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部:
方法名 | 描述 |
---|---|
has_permission |
用于对视图级别的权限进行控制。根据请求判断是否有权限访问视图。 |
has_object_permission |
用于对对象级别的权限进行控制。根据请求和特定对象判断是否有权限访问对象。 |
使用案例
定义自定义类
from rest_framework.permissions import BasePermission |
视图使用自定义类
from .permissions import IsXiaoMingPermission |
基于角色和权限的授权
在DRF中,基于角色和权限的授权是一种常见的权限控制机制。它通过将用户的角色和权限进行关联,来限制用户对API的访问和操作。
通常,基于角色和权限的授权包括以下几个步骤:
定义角色和权限
定义角色:按角色定义,用户可分为:管理员用户和普通用户
定义权限:创建、更新、删除、查看用户权限
关联角色和权限
管理员权限关联:创建、更新、删除、查看用户权限
普通用户权限关联:查看用户权限
用户角色分配
用户角色分配:用户1:管理员;用户2:普通用户
权限验证
自定义权限类:
from rest_framework.permissions import BasePermission |
限流
在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 |
局部限流配置
在视图集(MyViewSet)中进行了局部限流配置。通过设置throttle_classes属性,我们指定了两个限流类:AnonRateThrottle和UserRateThrottle,用于该视图集的限流。使用throttle_rates属性指定了每个限流类的速率,其中500/day表示匿名用户的速率为500次/天,50/hour表示用户的速率为50次/小时
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle |
数据过滤
在DRF中,数据过滤是指根据特定条件对API返回的数据进行筛选和过滤。DRF提供了多种方式来进行数据过滤,包括查询字符串参数、过滤器类、自定义过滤器等。
查询字符串参数
当使用查询字符串参数进行数据过滤时,可以通过重写视图类的get_queryset方法来根据查询字符串参数对查询集进行筛选。例如:
重写get_queryset方法
from rest_framework import generics |
如果我们向以下URL发送请求:GET /api/users?username=john
,返回以下数据:
[ |
过滤器类
首先定义了一个过滤器类UserFilter,它继承自filters.FilterSet。在过滤器类中,我们定义了两个过滤字段username和email,并指定了它们的查询条件(lookup_expr)。这里使用的是icontains,表示不区分大小写的包含匹配。
from django_filters import rest_framework as filters |
然后,我们在UserListAPIView中设置了filter_backends属性为[filters.DjangoFilterBackend],表示启用了过滤器类。同时,将filterset_class属性设置为UserFilter,以指定使用我们定义的过滤器类。
class UserListAPIView(generics.ListAPIView): |
现在,我们可以向API视图发送请求,并使用查询字符串参数来进行数据过滤。例如,可以发送以下请求:
GET /api/users?username=john&email=example.com |
自定义过滤器
创建了一个自定义过滤器类PriceRangeFilter,它实现了一个名为filter的方法。在该方法中,我们接收到的queryset参数是API视图的查询集,value参数是传递给过滤器的值。
假设过滤器的值是一个由连字符分隔的价格范围字符串,例如10-50。我们通过解析该字符串,将其分割为最小价格和最大价格,并使用price__range查询条件对查询集进行过滤。
class PriceRangeFilter: |
然后,我们在ProductListAPIView视图中设置了filter_backends属性,将PriceRangeFilter添加为过滤器后端。这样,当请求到达该视图时,将自动应用自定义过滤器类的过滤逻辑。
class ProductListAPIView(generics.ListAPIView): |
排序
在DRF(Django REST framework)中,可以使用排序功能对API的响应数据进行排序。DRF提供了多种排序选项和配置方式,使得排序变得非常灵活和易于使用。
排序可以在视图级别或全局级别进行配置。
全局配置排序
在DRF的设置文件(通常是settings.py)中,可以使用DEFAULT_FILTER_BACKENDS设置来配置默认的过滤器后端。可以将’rest_framework.filters.OrderingFilter’添加到该设置中,以启用全局级别的排序功能。
# settings.py |
通过字符串参数请求API,会自动进行排序:GET /api/products?ordering=name,price
视图配置局部排序
在视图级别,可以通过设置ordering属性来指定默认的排序字段。该属性可以是一个字符串或字符串列表,用于指定要应用的排序字段。如果指定了多个字段,数据将首先按照第一个字段排序,然后再按照后续字段进行排序。
from rest_framework import generics |
根据请求的查询字符串参数来动态指定排序字段。可以通过在视图类中定义ordering_fields属性来限制可用的排序字段列表,以防止不受控制的排序参数。
from rest_framework import generics |
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): |
自定义分页类
自定义分页类需要继承自 DRF 的 BasePagination 类,并实现相应的方法。paginate_queryset 方法用于实现分页逻辑,例如根据请求的页码和每页数据数量对查询集进行切片;get_paginated_response 方法用于返回分页后的响应,可以自定义响应的结构和格式。
例如:
from rest_framework.pagination import BasePagination |
文件上传
在settings.py文件中添加以下配置,示例使用本地文件系统进行存储:
# settings.py |
创建一个序列化器类,继承自DRF的serializers.Serializer或serializers.ModelSerializer。定义一个file字段用于接收上传的文件
# serializers.py |
创建一个视图类,继承自DRF的视图类,例如APIView或ViewSet。在该视图类中定义处理文件上传的方法,如post方法。
# views.py |
在URL路由中定义相应的URL模式,将请求映射到对应的视图处理函数。
# urls.py |
使用第三方包和扩展
扩展包 | 功能 |
---|---|
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 = [ |
创建Swagger文档信息:在你的项目中创建一个名为urls.py
的文件(如果不存在),并在其中添加以下内容:
from django.urls import path |
在浏览器中访问:http://localhost:8000/swagger/
http://localhost:8000/redoc/