Django REST framework 源码剖析-路由详解(Routers)
Django REST framework 源码剖析-路由详解(Routers)
- SimpleRouter
- DefaultRouter
- 以上两种路由注册方式必须配合视图集进行使用
- action 装饰器方式生成路由
路由分发方式
- 方式一
path('', include(router.urls)),
- 方式二
from rest_framework import routers
from myapp.viewsets import IndexActinosView
# 1.实例化路由对象
router = routers.SimpleRouter()
# 2.注册生成路由
router.register('actions', IndexActinosView, basename='actions')
# 3.添加路由
urlpatterns = []
urlpatterns += router.urls
SimpleRouter路由生成
- 创建viewset
from rest_framework.viewsets import ModelViewSet
from myapp.serializer import IndexActionsSerializer
from myapp.models import IndexActions
class IndexActinosView(ModelViewSet):
serializer_class = IndexActionsSerializer
queryset = IndexActions.objects.all()
- 注册路由
from rest_framework import routers
from myapp.viewsets import IndexActinosView
# 1.实例化路由对象
router = routers.SimpleRouter()
# 2.注册生成路由
router.register('actions', IndexActinosView, basename='actions')
# 3.添加路由
urlpatterns = []
urlpatterns += router.urls
- 生成路由
- 虽然你只看到两条路由, 但其实每一条路由后面都映射了可以保留的请求方式及action的映射
#包含:获取列表get,创建一条信息post
app/^actions/$ [name='studentmodel-list']
#包含:获取一条信息get,更新一条信息put,删除一条信息delete
app/^actions/(?P<id>[^/.]+)/$ [name='studentmodel-detail']
- 路由对象register方法参数介绍
# 1.实例化路由对象
router = routers.SimpleRouter()
# 2.注册生成路由
router.register('路由命名', 视图集, basename='路由名称前缀')
DefaultRouter路由生成
-
在Django REST framework(DRF)中,DefaultRouter 是 routers 模块提供的一个类,它用于自动为你的应用中的视图集(ViewSets)生成URL模式。使用 DefaultRouter 可以极大地简化URL配置的复杂性,特别是当你的应用包含多个与资源相关的视图集时。
-
DefaultRouter 为每个视图集自动生成以下URL模式:
- 列表视图(list view):返回资源对象列表
- 详情视图(detail view):返回单个资源对象
- 创建视图(create view):创建新的资源对象
- 更新视图(update view):更新现有的资源对象
- 删除视图(delete view):删除资源对象
-
创建viewset
from rest_framework.viewsets import ModelViewSet
from myapp.serializer import BookSerializer
from myapp.models import Book
class BookModelViewSet(ModelViewSet):
serializer_class = BookSerializer
queryset = Book.objects.all()
- 注册路由
#urls.py
from rest_framework import routers
from myapp.viewsets import BookModelViewSet
# 1.实例化路由对象
router = routers.DefaultRouter()
# 2.注册生成路由
router.register('book', BookModelViewSet)
# 3.添加路由
urlpatterns = []
urlpatterns += router.urls
- 生成路由
app/^actions/$ [name='studentmodel-list']
app/^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list']
app/^actions/(?P<id>[^/.]+)/$ [name='studentmodel-detail']
app/^actions/(?P<id>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-detail']
app/ [name='api-root']
app/<drf_format_suffix:format> [name='api-root']
- 我们看到中间还多了一些路由,是带有format正则匹配的,这些是用来获取纯粹json格式数据
# 例 http://127.0.0.1:8000/app/actions.json
app/^actions\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-list']
app/^actions/(?P<id>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='studentmodel-detail']
app/<drf_format_suffix:format> [name='api-root']
根路由概念
- 根路由是一个特殊的路由,用于处理对网站根目录的请求,并通常列出所有可用的API端点。
- 通常是一个特殊的路由,它位于路由系统的最顶层,用于处理对网站根目录(如/)的请求。在Django REST framework中,使用DefaultRouter时,会自动生成一个根路由,该路由会列出所有可用的API端点。这使得开发者能够方便地查看和理解API的结构。
两种路由生成方式区别
- SimpleRouter:最基本的路由映射方式,只会将视图集具备的混入类功能进行路由的生成
- DefaultRouter:对比与SimpleRouter更加高级,包含有drf根页面的路由,不只是视图集所包含的视图部分
额外操作的路由 (Routing for extra actions)
- 路由注册
from rest_framework.viewsets import ModelViewSet
from myapp.permissions import IsAdminOrIsSelf
from rest_framework.decorators import action
class UserViewSet(ModelViewSet):
...
@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf], url_path='set-password', url_name='set_password')
def set_password(self, request, pk=None):
...
- 路由生成
URL 模式: ^users/{pk}/set-password/$
URL 名称: 'user-set_password'
自定义路由器 (Custom Routers)
- url:表示被路由的 URL 的字符串
- mapping:HTTP 方法名称到视图方法的映射
- name:在 reverse 调用时使用的 URL 名称。
- initkwargs:实例化视图时应传递的任何其他参数的字典。请注意,detail,basename 和 suffix 参数是视图集内省保留的,并也可由可浏览 API 使用来生成视图名称和痕迹链接。
# url参数可能包含以下格式字符串:
{prefix} —— 用于这组路由的 URL 前缀。
{lookup} —— 用于匹配单个实例的查找字段。
{trailing_slash} —— “/” 或空字符串,取决于 trailing_slash 参数。
# name参数可能包含以下格式字符串:
{basename} —— 用于创建的 URL 名称的基础。
自定义动态路由 (Customizing dynamic routes)
- url:表示被路由的 URL 的字符串。
- name:在 reverse 调用时使用的 URL 名称。可能包含以下格式字符串:
- initkwargs:实例化视图时应传递的任何其他参数的字典。
# url参数可能包含以下格式字符串:
{url_path} —— 格式字符串
# name参数可能包含以下格式字符串:
{basename} —— 用于创建的 URL 名称的基础。
{url_name} —— 提供给 @action 的 url_name。
示例: 只路由 list 和 retrieve 操作,不使用斜杠约定
- 自定义路由
from rest_framework.routers import Route, DynamicRoute, SimpleRouter
class CustomReadOnlyRouter(SimpleRouter):
"""
用于只读 API 的路由器,不使用尾部斜杠。
"""
routes = [
Route(
url=r'^{prefix}$',
mapping={'get': 'list'},
name='{basename}-list',
detail=False,
initkwargs={'suffix': 'List'}
),
Route(
url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'},
name='{basename}-detail',
detail=True,
initkwargs={'suffix': 'Detail'}
),
DynamicRoute(
url=r'^{prefix}/{lookup}/{url_path}$',
name='{basename}-{url_name}',
detail=True,
initkwargs={}
)
]
- 视图类
from rest_framework import viewsets
from rest_framework.decorators import action
from myapp.serializer import UserSerializer
from myapp.models import User
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
提供标准操作的视图集
"""
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'username'
@action(detail=True)
def group_names(self, request, pk=None):
"""
返回给定用户所属的所有组名称的列表。
"""
user = self.get_object()
groups = user.groups.all()
return Response([group.name for group in groups])
- 使用自定义路由
from myapp.routers import CustomReadOnlyRouter
router = CustomReadOnlyRouter()
router.register('users', UserViewSet)
urlpatterns = []
urlpatterns += router.urls
- 生成映射
/users GET list user-listAction
/users/{username} GET retrieve user-detail
/users/{username}/group-names GET group_names user-group-names