
视图集是 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 删除。