五、drf路由组件

drf路由组件

一、基本使用

1. 步骤

  • 导入routers模块

    from rest_framework import routers
    
  • 有两个类,实例化(二选一)得到该对象

    # routers.DefaultRouter
    # routers.SimpleRouter
    router = routers.SimpleRouter()
    
  • 注册

    # router.register('前缀','继承自ModelViewSet试图类','别名') 不要加斜杠
    router.register('book',view.BookViewSet) # 不要加斜杠
    
  • 自动生成路由

    # router.urls 就是自动生成的路由,直接添加到urlpatterns中
    urlpatterns += router.urls
    

2. 代码实现

# 第一步
from rest_framework import routers
# 第二步
router = routers.SimpleRouter()
# 第三步
router.register('books',views.BooksView) # 不要加斜杠
urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
# 第四步
urlpatterns += router.urls

3. 总结

1.适用范围:只有继承了ViewSetMixin类的视图,才可以使用路由组件快速生成路由
2.快速生成的路由有2种路由类:SimpleRouter、DefaultRouter
3.2种路由类的区别
	SimpleRouter生成的路由
    	^admin/
        ^books/$ [name='book-list']
        ^books/(?P<pk>[^/.]+)/$ [name='book-detail']
    DefaultRouter生成的路由 华而不实
    	^admin/
        ^books/$ [name='book-list']
        ^books.(?P<format>[a-z0-9]+)/?$ [name='book-list']
        ^books/(?P<pk>[^/.]+)/$ [name='book-detail']
        ^books/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='book-detail']
        ^books/(?P<pk>[^/.]+)/get_1/$ [name='book-get-1']
        ^.(?P<format>[a-z0-9]+)/?$ [name='api-root']

二、视图中的action装饰器

from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response

from rest_framework.decorators import action

from app01.models import Book
from app01.serializer import BookModelSerializer


class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
	"""
    提示: action是一个装饰器    
    导入方式: from rest_framework.decorators import action 
    作用: 给继承自ModelViewSet的视图类中定义的函数也添加路由
	"""
    @action(methods=['GET'], detail=True)
    def get_two(self, request, pk):
        print(pk)
        book_queryset = self.get_queryset()[:2]
        serializer = self.serializer_class(instance=book_queryset, many=True)
        return Response(serializer.data)

    @action(methods=['GET'], detail=False)
    def get_all(self, request):
        book_queryset = self.get_queryset()
        serializer = self.serializer_class(instance=book_queryset, many=True)
        return Response(serializer.data)

参数详解

def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
methods: 第一个参数,传一个列表,列表中放请求方式
    提示: 由下面的源码得知如果没有指定参数, 默认是get方法. 且方法可以大写, 可以小写. 大写的话就会将大写的字符串转换成小写
    methods = ['get'] if (methods is None) else methods
    methods = [method.lower() for method in methods]
detail: 指定布尔值. 控制路由匹配的形式. True可以匹配单条数据, False可以匹配多条数据
    True时匹配规则:  ^app02/ ^books/(?P<pk>[^/.]+)/get_two/$ [name='book-get-two']
    False时匹配规则: ^app02/ ^books/get_two/$ [name='book-get-two']

总结

1.detail=True是在需要传入pk值时使用,detail=False相反
2.action装饰器的使用场景:对查询数据有限制时使用
3.为什么使用action装饰器?
    因为快速生成路由组件无法手动添加路由 和 无法修改视图类中方法名, 通过action就可以快速实现.
4.使用流程
    (1). 导入: from rest_framework.decorators import action
    (2). 在视图中为视图中的方法添加装饰器
        class BookView(ViewSet):
            @action(method=["post", ], detail=True)  
            def login():
                ...
        参数介绍: 
            method:  不指定, 默认就是get方法. 如果指定大写, 默认就会转成小写.
            detail:  不指定, 会抛出异常. 指定True, False表示的路由不一样. 看3
    (3). 路由中就会新增一个路由
          detail=True时:  url(r'^books/(?P<pk>)/login/$')
          detail=False时: url(r'^books/login/$')

三、补充

1. 路由生成的两种方式

urlpatterns = [
    # 1. 生成的路由第一种添加方法
    url(r'', include(router.urls))
]
# 2. 生成的路由第二种添加方法
urlpatterns += router.urls

2. 关于路由组件的使用

路由组自动生成的原理: 自动生成路由, 自动配置actions参数.
也就是说只要是继承了ViewSetMixin的视图类, 都可以配置路由组件.
原文地址:https://www.cnblogs.com/borntodie/p/14330789.html