DRF 版本控制 #
一、版本控制概述 #
1.1 为什么需要版本控制 #
- API接口变更时保持向后兼容
- 允许客户端逐步迁移
- 支持多版本并存
1.2 版本控制方式 #
| 方式 | 说明 | 示例 |
|---|---|---|
| URLPathVersioning | URL路径 | /api/v1/articles/ |
| NamespaceVersioning | URL命名空间 | /v1/articles/ |
| HostNameVersioning | 域名 | v1.api.example.com |
| QueryParameterVersioning | 查询参数 | /api/articles/?version=1 |
| AcceptHeaderVersioning | Accept头 | Accept: application/json; version=1 |
二、URLPathVersioning #
2.1 配置 #
python
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version',
}
2.2 URL配置 #
python
urlpatterns = [
path('api/<str:version>/articles/', ArticleViewSet.as_view({'get': 'list'})),
]
2.3 访问方式 #
text
GET /api/v1/articles/
GET /api/v2/articles/
2.4 视图中获取版本 #
python
class ArticleViewSet(viewsets.ModelViewSet):
def get_serializer_class(self):
version = self.request.version
if version == 'v1':
return ArticleSerializerV1
return ArticleSerializerV2
三、QueryParameterVersioning #
3.1 配置 #
python
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.QueryParameterVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
'VERSION_PARAM': 'version',
}
3.2 访问方式 #
text
GET /api/articles/?version=v1
GET /api/articles/?version=v2
四、AcceptHeaderVersioning #
4.1 配置 #
python
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
}
4.2 访问方式 #
bash
curl -H "Accept: application/json; version=v1" http://api.example.com/articles/
curl -H "Accept: application/json; version=v2" http://api.example.com/articles/
五、版本化ViewSet #
5.1 多版本ViewSet #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
def get_serializer_class(self):
version = self.request.version
if version == 'v1':
return ArticleSerializerV1
elif version == 'v2':
return ArticleSerializerV2
return ArticleSerializer
def get_queryset(self):
queryset = Article.objects.all()
version = self.request.version
if version == 'v1':
queryset = queryset.filter(is_published=True)
return queryset
5.2 版本化URL #
python
from rest_framework.routers import DefaultRouter
from .views import ArticleV1ViewSet, ArticleV2ViewSet
router_v1 = DefaultRouter()
router_v1.register(r'articles', ArticleV1ViewSet)
router_v2 = DefaultRouter()
router_v2.register(r'articles', ArticleV2ViewSet)
urlpatterns = [
path('api/v1/', include(router_v1.urls)),
path('api/v2/', include(router_v2.urls)),
]
六、版本弃用 #
6.1 弃用警告 #
python
from rest_framework.response import Response
class ArticleViewSet(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
if request.version == 'v1':
response['X-API-Deprecated'] = 'This version is deprecated. Please migrate to v2.'
return response
6.2 版本过期处理 #
python
from rest_framework.exceptions import APIException
class VersionExpired(APIException):
status_code = 410
default_detail = '此API版本已过期,请使用最新版本'
class ArticleViewSet(viewsets.ModelViewSet):
def initial(self, request, *args, **kwargs):
if request.version == 'v0':
raise VersionExpired()
super().initial(request, *args, **kwargs)
七、总结 #
本章学习了DRF版本控制:
- URLPathVersioning:URL路径版本
- QueryParameterVersioning:查询参数版本
- AcceptHeaderVersioning:请求头版本
- 版本化ViewSet:多版本视图
- 版本弃用:弃用和过期处理
版本控制让API演进更加平滑!
最后更新:2026-03-28