视图集是 DRF 提供的用于统一管理多个相关视图逻辑的类。它将常见的 CRUD 操作(如 list
, create
, retrieve
, update
, destroy
)封装在一个类中,并支持通过路由器(Router)自动生成 RESTful 风格的 URL。
核心特点:
GET /users/
和 GET /users/{id}/
)。Mixin
类结合,快速实现标准化操作。@action
装饰器)。Router
自动生成 URL(如 /users/
和 /users/{id}/
)。Mixin
组合功能,或添加自定义动作。视图集类 | 继承关系 | 支持的 Mixin | 功能描述 |
---|---|---|---|
| 直接继承 | 无,需手动实现所有方法(如 | 最基础的视图集,完全自由但需大量手动编码 |
| 继承 | 需手动组合 Mixin(如 | 灵活组合 Mixin,适合需要自定义逻辑的场景 |
| 继承 |
| 全功能视图集,自动支持 CRUD 操作 |
| 继承 |
| 仅支持 |
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
class UserViewSet(ViewSet):
def list(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
使用 Router
自动生成路由:
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls
生成的路由:
GET /users/
→ list()
POST /users/
→ create()
特性 | DefaultRouter | SimpleRouter |
---|---|---|
API 根视图 | 自动生成 | 不生成根视图 |
格式后缀 | 支持 | 不支持格式后缀 |
URL 路径风格 | 严格以斜杠 | 可配置是否包含斜杠(默认包含) |
额外功能 | 提供更丰富的超链接 API 展示 | 轻量级,只生成基础路由 |
DRF 的路由器(如 DefaultRouter
和 SimpleRouter
)通过以下机制自动生成 URL:
ModelViewSet
)定义了标准化的方法(list
, create
, retrieve
, update
, destroy
),这些方法对应 RESTful 的 CRUD 操作:list()
→ GET /users/
(获取列表)create()
→ POST /users/
(创建对象)retrieve()
→ GET /users/{pk}/
(获取单个对象)update()
→ PUT /users/{pk}/
(全量更新)partial_update()
→ PATCH /users/{pk}/
(部分更新)destroy()
→ DELETE /users/{pk}/
(删除对象)# SimpleRouter 的默认路由规则
routes = [
# 列表路由(不带 {pk})
Route(
url=r'^{prefix}/$',
mapping={'get': 'list', 'post': 'create'},
name='{basename}-list',
detail=False,
),
# 详情路由(带 {pk})
Route(
url=r'^{prefix}/{lookup}/$',
mapping={
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
},
name='{basename}-detail',
detail=True,
),
]
prefix
:注册时的 URL 前缀(如 users
)。lookup
:对象标识符(默认是 pk
)。mapping
:HTTP 方法与视图集方法的映射。router.register()
注册视图集时,路由器会检查视图集是否实现了特定方法:list
方法 → 生成列表路由(GET /users/
)。create
方法 → 允许 POST /users/
。retrieve
方法 → 生成详情路由(GET /users/{pk}/
)。update
, destroy
)同理。以 SimpleRouter
为例,其核心逻辑如下:
class SimpleRouter:
def get_urls(self):
urls = []
# 遍历所有预定义的路由规则(如列表路由、详情路由)
for route in self.routes:
# 动态生成 URL 正则表达式和视图函数
url = route.url.format(prefix=self.prefix, lookup=self.lookup)
view = self.viewset.as_view(route.mapping)
urls.append(url(path=url, view=view, name=route.name))
return urls
路由器通过字符串模板(如 r'^{prefix}/$'
)生成具体的 URL 正则表达式。例如,注册 users
时,会生成 r'^users/$'
和 r'^users/{pk}/$'
。
通过 viewset.as_view(mapping)
将 HTTP 方法(如 GET
)映射到视图集的对应方法(如 list
)。
假设需要为 UserViewSet
添加一个 search
动作:
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
class UserViewSet(ModelViewSet):
@action(detail=False, methods=['get'], url_path='search')
def search_users(self, request):
# 实现搜索逻辑
return Response(...)
from rest_framework.routers import SimpleRouter, Route
class CustomRouter(SimpleRouter):
routes = [
# 默认的列表路由和详情路由
*SimpleRouter.routes,
# 添加自定义路由
Route(
url=r'^{prefix}/search/$',
mapping={'get': 'search_users'},
name='{basename}-search',
detail=False,
),
]
router = CustomRouter()
router.register(r'users', UserViewSet)
GET /users/
→ list()
GET /users/search/
→ search_users()
GET /users/{pk}/
→ retrieve()
list
对应 GET /users/
),结合视图集的方法检测,动态生成 URL。DefaultRouter
提供更完整的 RESTful 支持(API 根视图、格式后缀)。SimpleRouter
更轻量,适合简单场景。routes
规则,实现自定义 URL 设计。DefaultRouter
自动生成的根路径(/
)会列出所有注册的视图集端点。/
返回:{
"users": "http://localhost:8000/users/",
"groups": "http://localhost:8000/groups/"
}
basename
控制链接名称。from rest_framework.mixins import ListModelMixin, CreateModelMixin
class UserViewSet(ListModelMixin, CreateModelMixin, GenericViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
支持 GET /users/
(列表)和 POST /users/
(创建)。
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
自动支持 GET
, POST
, PUT
, PATCH
, DELETE
。
class UserViewSet(ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
仅支持 GET /users/
(列表)和 GET /users/{id}/
(详情)。
@action
装饰器的使用@action
是 DRF 中用于在视图集(ViewSet)中定义自定义动作的核心装饰器,可以将任意方法暴露为 API 端点。下面通过更多场景详细说明其用法。
detail
:True
:操作单个对象(如 /users/{id}/action_name/
)。False
:操作列表或集合(如 /users/action_name/
)。methods
: 允许的 HTTP 方法(如 ['get', 'post']
)。url_path
: 自定义 URL 路径(默认用方法名)。url_name
: 路由名称(用于反向解析)。from rest_framework.decorators import action
from rest_framework.response import Response
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# 获取所有管理员用户
@action(detail=False, methods=['get'])
def admins(self, request):
admins = User.objects.filter(is_admin=True)
serializer = self.get_serializer(admins, many=True)
return Response(serializer.data)
GET /users/admins/
detail=False
表示操作对象是整个用户列表的筛选。class UserViewSet(ModelViewSet):
@action(detail=False, methods=['post'], url_path='bulk-delete')
def bulk_delete(self, request):
ids = request.data.get('ids', [])
User.objects.filter(id__in=ids).delete()
return Response({'status': '批量删除成功'})
POST /users/bulk-delete/
url_path
自定义 URL 路径。ids
列表,批量删除用户。detail=True
)class UserViewSet(ModelViewSet):
@action(detail=True, methods=['post'], url_path='activate')
def activate_user(self, request, pk=None):
user = self.get_object() # 自动根据 pk 获取对象
user.is_active = True
user.save()
return Response({'status': '用户已激活'})
POST /users/{pk}/activate/
detail=True
表示操作单个用户实例。pk
参数自动从 URL 中捕获(如 /users/5/activate/
中的 5
)。class ProductViewSet(ModelViewSet):
@action(detail=True, methods=['get', 'post'], url_path='price-history')
def price_history(self, request, pk=None):
product = self.get_object()
if request.method == 'GET':
# 获取价格历史
history = PriceHistory.objects.filter(product=product)
serializer = PriceHistorySerializer(history, many=True)
return Response(serializer.data)
elif request.method == 'POST':
# 添加新价格记录
serializer = PriceHistorySerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save(product=product)
return Response(serializer.data)
GET /products/{pk}/price-history/
→ 获取历史价格POST /products/{pk}/price-history/
→ 添加新价格class OrderViewSet(ModelViewSet):
@action(detail=True, methods=['get'], url_path='items/(?P<category>[^/.]+)')
def filter_items_by_category(self, request, pk=None, category=None):
order = self.get_object()
items = order.items.filter(category=category)
serializer = OrderItemSerializer(items, many=True)
return Response(serializer.data)
GET /orders/{pk}/items/electronics/
→ 筛选订单中电子类商品url_path
中使用正则表达式捕获参数(category
)。category
)。class UserViewSet(ModelViewSet):
@action(detail=True, methods=['post'], permission_classes=[IsAdminUser])
def promote_to_admin(self, request, pk=None):
user = self.get_object()
user.is_admin = True
user.save()
return Response({'status': '用户已升级为管理员'})
permission_classes
覆盖视图集的默认权限。class UserViewSet(ModelViewSet):
def get_serializer_class(self):
if self.action == 'change_password':
return ChangePasswordSerializer
return UserSerializer
@action(detail=True, methods=['post'])
def change_password(self, request, pk=None):
user = self.get_object()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user.set_password(serializer.validated_data['password'])
user.save()
return Response({'status': '密码已修改'})
detail=True
的动作,pk
自动从 URL 捕获。url_path
中定义(如示例 5)。url_path
参数覆盖默认路径(如 url_path='custom-path'
)。throttle_classes
:python复制@action(detail=False, methods=['get'], throttle_classes=[UserRateThrottle])
@action
的核心价值:扩展视图集,支持非标准业务逻辑(如 /users/{id}/activate/
)。detail
: 区分列表级 vs 对象级操作。methods
: 定义支持的 HTTP 方法。url_path
: 自定义 URL 路径。验证自定义动作:
通过 DRF 的 Web 界面或 curl
测试:
# 测试示例1
curl http://localhost:8000/users/admins/
# 测试示例3
curl -X POST http://localhost:8000/users/5/activate/
组件/技术 | 适用场景 | 核心优势 |
---|---|---|
| 完全自定义逻辑的非标准接口 | 自由度高 |
| 需要灵活组合 Mixin 的场景(如仅支持部分操作) | 可定制化 + DRF 核心功能 |
| 标准 CRUD 接口(如后台管理) | 全自动 + 零编码 |
| 只读接口(如公开数据查询) | 安全 + 简洁 |
| 扩展自定义动作(如 | 灵活扩展非标准操作 |
最佳实践:
ModelViewSet
:快速实现标准 CRUD。@action
扩展功能:添加非标准业务逻辑。DefaultRouter
适合完整 API,SimpleRouter
适合轻量级需求。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。