一、路由的写法
1、原始写法
(1)介绍
- 是指手动编写路由规则的方式。
- 使用
path()
函数或re_path()
函数来定义路由规则,并将其与对应的视图函数或类关联起来。
(2)示例
- 假设有一个名为
book
的应用,它包含了一个处理图书列表的视图函数book_list
,以及一个处理单个图书详情的视图函数book_detail
。 - 我们可以通过以下方式手动编写路由规则:
from django.urls import path
from book.views import book_list, book_detail
urlpatterns = [
path('books/', book_list, name='book_list'),
path('books/<int:book_id>/', book_detail, name='book_detail'),
]
- 在这个例子中
- 第一条路由规则匹配到
/books/
路径,并将其与book_list
视图函数关联起来。 - 第二条路由规则匹配到
/books/<int:book_id>/
路径,其中<int:book_id>
是一个路径参数,用于匹配一个整型的图书ID,并将其传递给book_detail
视图函数。
- 第一条路由规则匹配到
2、手动映射的写法
(1)介绍
- 路由器将HTTP方法与视图集中的相应操作方法进行映射。
- 在使用路由器时,需要先定义一个视图集,然后将其与路由器关联起来。
- 最后,在URL配置中使用路由器生成的路由规则。
(2)示例
from rest_framework.routers import DefaultRouter
from book.views import BookModelViewSet
urlpatterns = [
path("books/", BookModelViewSet.as_view({"get": "list","post": "create"})),
path("books/<int:pk>/", BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]
3、小结
- 手动编写路由规则更加灵活,可以对每个URL路径指定具体的视图函数或类。
- 可以根据需求选择手动编写路由规则或使用路由器自动生成路由规则。
- 使用路由器可以简化代码,特别适用于处理一组相关操作的视图函数或类。
二、自动生成路由
前提:继承了ViewSetMixin。对于视图集ViewSet,除了可以手动进行URL配置指明请求方式与action处理函数之间的对应关系外,还可以使用路由Router来自动生成路由信息。
在 Django REST framework 中,SimpleRouter
和 DefaultRouter
都是用于简化 URL 配置和路由管理的工具,它们可以帮助开发者快速创建符合 RESTful 设计原则的 API 路由。
1、SimpleRouter
(1)使用步骤
- 导入一个路由类
from rest_framework.routers import SimpleRouter
- 实例化得到对象
router=SimpleRouter()
- 执行对象的方法
router.register('books',BookView,'books')
- 对象.属性 拿到值
print(router.urls)
urlpatterns = [
path('request/', BookView.as_view()),
path('publish/', PublishView.as_view({'get': 'login'})),
]
- 把自动生成的路由,放到 urlpatterns中
方案一:urlpatterns+=router.urls
方案二:urlpatterns = [
path('', include(router.urls)),
] # 用来代替上面的urlpatterns,优势在于我前面还可以再加前缀
比如我用方案一生成的url是 http://127.0.0.1:8000/app01/books/
path('api/v1/', include(router.urls)) # 添加前缀
而用方案二我可以生成 http://127.0.0.1:8000/app01/api/v1//books/
-
4和5是我们自动生成的路由
-
SimpleRouter自动生成的路由不包括自定义的视图函数login,只会生成:(指定的prefix:books前缀拼接xxx路径,单独访问127.0.0.1:8000:/app01/会返回404报错)
- (1)
app01/books/$ [name='books-list']
––> 相当于re_path(r'^app01/books/$')
- (2)
app01/^books/(?P<pk>[^/.]+)/$ [name='books-detail']
––> 相当于re_path(r'^app01/book/<pk>/$')
- (1)
(2)生成URL的方式
2、DefaultRouter
(1)使用步骤
- 导入一个路由类
from rest_framework.routers import DefaultRouter
- 实例化得到对象
router=DefaultRouter()
- 执行对象的方法
router.register('books',BookView,'books')
- 对象.属性 拿到值
print(router.urls)
urlpatterns = [
path("books/", BookView.as_view({"get": "list", "post": "create"})),
path("books/<int:pk>/", BookView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]
- 把自动生成的路由,放到 urlpatterns中
方案一:urlpatterns+=router.urls
方案二:urlpatterns = [
path('', include(router.urls)),
] # 用来代替上面的urlpatterns,优势在于我前面还可以再加前缀
比如我用方案一生成的url是 http://127.0.0.1:8000/app01/books/
path('api/v1/', include(router.urls)) # 添加前缀
而用方案二我可以生成 http://127.0.0.1:8000/app01/api/v1//books/
-
4和6是SimpleRouter自动生成的路由
-
5和7是另一种格式正则表达式,再加上一个根路由
-
DefaultRouter自动生成的路由也不包括自定义的视图函数login
- (1)
app01/ ^books\.(?P<format>[a-z0-9]+)/?$ [name='books-list']
––> 相当于re_path(r'^app01/books/$')
- (2)
app01/ ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='books-detail']
––> 相当于re_path(r'^app01/book/<pk>/$')
- (1)
(2)生成URL的方式
(3)与SimpleRouter不同的地方
- 127.0.0.1:8000/app01/books.json可以得到原生的
json数据
- 根路由,访问127.0.0.1:8000不会返回404报错,而是返回下面的页面
三、使用action装饰器自定义详细路由
作用:修饰自定义视图函数,使之能够进行自动路由映射
因为上面两种自动映射路由方法都不会映射自定义视图方法所以我们选择装饰器。
@action(methods=['get'], detail=False, url_path='latest')
- urls.py
path("books/", BookModelViewSet.as_view({"get": "latest"})),
- views.py
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app01.models import Book, Publish
from app01.serializers import BookSerializer, PublishSerializer
# action作用:修饰自定义视图函数,使之能够进行自动路由映射
from rest_framework.decorators import action
class BookModelViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
# methods: 映射的请求方式
# url_path: 路径拼接尾缀,默认值是函数名字
# detail:
# True ---> 路径拼接是: 前缀(prefix) + pk正则分组 + 尾缀(url_path)
# False ---> 路径拼接是: 前缀(prefix) + 尾缀(url_path)
@action(methods=['get'], detail=False, url_path='latest')
def latest(self, request, *args, **kwargs):
book = self.queryset.latest('id') # 最新发布的书
serializer = self.get_serializer(instance=book)
return Response(data=serializer.data)
四、视图类对象.action
self.action:可以看出请求的是谁,根据不同的请求返回不同的序列化器。(这种场景使用概率比较小)
使用:
from rest_framework.viewsets import ModelViewSet
from testdjango.models import BookInfo
from book_drf.serializer import BookSerializer
from rest_framework.response import Response
class Books(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookSerializer
# 根据这方法可以看出请求的是谁,返回哪个序列化器
def get_serializer_class(self):
if self.action == 'lastdata':
return BookSerializer
else:
return BookSerializer
# 定义如果超出那五个方法之外的方法,需要使用action装饰器
@action(methods=['get'], detail=True)
def lastdata(self, request, pk):
# 使用self.action 获取请求的是哪个方法,可以根据请求的是哪个
print(self.action)
book = BookInfo.objects.get(id=pk)
ser = self.get_serializer_class(book)
return Response(ser.data)