DRF 路由基础 #
一、路由概述 #
1.1 什么是Router #
Router是DRF提供的URL路由工具,能够自动将ViewSet映射到URL,大大简化URL配置。
text
传统URL配置
┌─────────────────────────────────────┐
│ path('articles/', ArticleList.as_view()) │
│ path('articles/<int:pk>/', ArticleDetail.as_view()) │
│ path('articles/create/', ArticleCreate.as_view()) │
│ ...更多URL配置 │
└─────────────────────────────────────┘
Router自动生成
┌─────────────────────────────────────┐
│ router.register('articles', ArticleViewSet) │
│ 自动生成所有CRUD URL │
└─────────────────────────────────────┘
1.2 Router类型 #
| Router | 说明 |
|---|---|
| DefaultRouter | 包含API根视图 |
| SimpleRouter | 简洁版,无根视图 |
二、DefaultRouter #
2.1 基本用法 #
python
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = router.urls
2.2 生成的URL #
| URL | 方法 | 操作 |
|---|---|---|
| /articles/ | GET | list |
| /articles/ | POST | create |
| /articles/{id}/ | GET | retrieve |
| /articles/{id}/ | PUT | update |
| /articles/{id}/ | PATCH | partial_update |
| /articles/{id}/ | DELETE | destroy |
| / | GET | API根视图 |
2.3 集成到项目 #
python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
三、SimpleRouter #
3.1 基本用法 #
python
from rest_framework.routers import SimpleRouter
from .views import ArticleViewSet
router = SimpleRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = router.urls
3.2 与DefaultRouter区别 #
| 特性 | DefaultRouter | SimpleRouter |
|---|---|---|
| API根视图 | 有 | 无 |
| 格式后缀 | 支持 | 支持 |
| 适用场景 | 完整API | 简单API |
四、register方法 #
4.1 基本注册 #
python
router.register(r'articles', ArticleViewSet)
4.2 指定basename #
python
router.register(r'articles', ArticleViewSet, basename='article')
basename用于生成URL名称:
article-listarticle-detail
4.3 多个ViewSet注册 #
python
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
router.register(r'users', UserViewSet)
router.register(r'categories', CategoryViewSet)
router.register(r'tags', TagViewSet)
五、ViewSet URL映射 #
5.1 ModelViewSet映射 #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
自动生成的URL:
| URL模式 | HTTP方法 | ViewSet方法 |
|---|---|---|
| {prefix}/ | GET | list |
| {prefix}/ | POST | create |
| {prefix}/{lookup}/ | GET | retrieve |
| {prefix}/{lookup}/ | PUT | update |
| {prefix}/{lookup}/ | PATCH | partial_update |
| {prefix}/{lookup}/ | DELETE | destroy |
5.2 ReadOnlyModelViewSet映射 #
python
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
只生成:
| URL模式 | HTTP方法 | ViewSet方法 |
|---|---|---|
| {prefix}/ | GET | list |
| {prefix}/{lookup}/ | GET | retrieve |
5.3 自定义ViewSet映射 #
python
from rest_framework import viewsets, mixins
class ArticleViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
viewsets.GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
六、自定义action路由 #
6.1 detail=True #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
pass
生成URL:/articles/{pk}/publish/
6.2 detail=False #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=False, methods=['get'])
def published(self, request):
pass
生成URL:/articles/published/
6.3 自定义url_path #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=True, methods=['post'], url_path='change-status')
def change_status(self, request, pk=None):
pass
生成URL:/articles/{pk}/change-status/
6.4 多个HTTP方法 #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=True, methods=['get', 'post'])
def comments(self, request, pk=None):
if request.method == 'GET':
pass
elif request.method == 'POST':
pass
七、lookup_field配置 #
7.1 使用slug #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'slug'
URL变为:/articles/{slug}/
7.2 lookup_url_kwarg #
python
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'article_slug'
URL配置:
python
router.register(r'articles', ArticleViewSet)
URL变为:/articles/{article_slug}/
八、完整示例 #
8.1 视图集 #
python
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
lookup_field = 'slug'
@action(detail=False, methods=['get'])
def published(self, request):
articles = self.get_queryset().filter(is_published=True)
serializer = self.get_serializer(articles, many=True)
return Response(serializer.data)
@action(detail=False, methods=['get'])
def draft(self, request):
articles = self.get_queryset().filter(is_published=False)
serializer = self.get_serializer(articles, many=True)
return Response(serializer.data)
@action(detail=True, methods=['post'])
def publish(self, request, slug=None):
article = self.get_object()
article.is_published = True
article.save()
return Response({'status': 'published'})
@action(detail=True, methods=['post'])
def like(self, request, slug=None):
article = self.get_object()
article.likes.add(request.user)
return Response({'status': 'liked'})
8.2 URL配置 #
python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet, UserViewSet, CategoryViewSet
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
router.register(r'users', UserViewSet)
router.register(r'categories', CategoryViewSet, basename='category')
urlpatterns = [
path('api/v1/', include(router.urls)),
]
8.3 生成的URL列表 #
text
/api/v1/ # API根视图
/api/v1/articles/ # 文章列表
/api/v1/articles/published/ # 已发布文章
/api/v1/articles/draft/ # 草稿文章
/api/v1/articles/{slug}/ # 文章详情
/api/v1/articles/{slug}/publish/ # 发布文章
/api/v1/articles/{slug}/like/ # 点赞文章
/api/v1/users/ # 用户列表
/api/v1/users/{id}/ # 用户详情
/api/v1/categories/ # 分类列表
/api/v1/categories/{id}/ # 分类详情
九、总结 #
本章学习了DRF路由基础:
- Router类型:DefaultRouter和SimpleRouter
- register方法:注册ViewSet
- URL映射:自动生成CRUD URL
- 自定义action:添加自定义路由
- lookup_field:自定义查找字段
让我们继续学习路由进阶!
最后更新:2026-03-28