1. 程式人生 > 實用技巧 >大話設計模式讀書筆記(裝飾模式)

大話設計模式讀書筆記(裝飾模式)

一. 基本使用#

Copy
from django.conf.urls import url

# 第一步:從rest_framework包中匯入routers模組
from rest_framework import routers
from .views import BookModelViewSet

# 第二步:有兩個類,例項化得到物件
"""
routers.SimpleRouter()   生成2條路由
routers.DefaultRouter()  生成6條路由
"""
# router = routers.SimpleRouter()
router = routers.DefaultRouter()

# 第三步:註冊
''' def register(self, prefix, viewset, basename=None, base_name=None): """ prefix: 字首. viewset: 繼承自ModelViewSet檢視類 basename: 別名 """ ''' router.register('books', BookModelViewSet) # 提示: 不需要加斜槓 urlpatterns = [] # 第四步: 通過router.urls會自動生成的路由列表, 只需要加入到原路由中即可 urlpatterns += router.urls

使用SimpleRouter()例項化的路由格式

Copy
# 專案中列印
# print(router.urls)
'''
[
    <RegexURLPattern book-list ^books/$>,
     <RegexURLPattern book-detail ^books/(?P<pk>[^/.]+)/$>
 ]
'''

# 瀏覽器中列印
'''
# 解析: [^/.]+ 
    [^/.]+ 中^表示取反 意思就是匹配任意其它內容, /就不匹配. 
    +號表示且匹配1個或者多個
    
^app01/ ^books/$ [name='book-list']
^app01/ ^books/(?P<pk>[^/.]+)/$ [name='book-detail']
'''

使用DefaultRouter()類例項化的路由格式

Copy
# 專案中列印
'''
[
    <RegexURLPattern book-list ^books/$>, 
    <RegexURLPattern book-list ^books\.(?P<format>[a-z0-9]+)/?$>, 
    <RegexURLPattern book-detail ^books/(?P<pk>[^/.]+)/$>, 
    <RegexURLPattern book-detail ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>, <RegexURLPattern api-root ^$>,
     <RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>
 ]
'''

# 瀏覽器中列印
'''
^app01/ ^books/$ [name='book-list']
^app01/ ^books\.(?P<format>[a-z0-9]+)/?$ [name='book-list']
^app01/ ^books/(?P<pk>[^/.]+)/$ [name='book-detail']
^app01/ ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail']
^app01/ ^$ [name='api-root']
^app01/ ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
'''

總結#

Copy
1. 使用範圍: 只有繼承了 ViewSetMixin 類的檢視, 才可以使用路由元件快速生成路由
2. 快速生成路由的2種路由類: SimpleRouter, DefaultRouter
3. 路由中使用:
    from django.conf.urls import include
    from rest_framework.routes import SimpleRouter
    router = SimpleRouter()
    router.register('路由字首', 繼承了ViewSetMixin類的檢視, 用於反向解析的別名)
    urlpatterns = [
    	url('', include(router.urls)), # 新增路由的第二種方式
    ]
    urlpatterns += router  # 新增路由的第一種方式

二. 檢視中action裝飾器#

Copy
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的檢視類中定義的函式也新增路由
    
    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']
        """
    '''

    # detail=False時瀏覽器輸入 http://127.0.0.1:8011/app02/books/get_two/
    # detail=True時瀏覽器輸入:  http://127.0.0.1:8011/app02/books/1/get_two/

    @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)

使用action添加了路由以後的detail=True時的路由格式

使用action添加了路由以後的detail=False時的路由格式

總結#

Copy
# 為什麼使用action裝飾器?
    因為快速生成路由元件無法手動新增路由 和 無法修改檢視類中方法名, 通過action就可以快速實現.

# 使用流程
    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/$')

三. 補充: 路由生成的二種方法#

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

四. 補充: 關於路由元件的使用#

Copy
路由組自動生成的原理: 自動生成路由, 自動配置actions引數.
也就是說只要是繼承了ViewSetMixin的檢視類, 都可以配置路由元件.