2015-02-04 14 views
1

我有一個非常小的基本站點,有一些視圖。幾乎所有的視圖都會與外部API進行一些交互。使用中間件添加參數以查看django中的函數

在每個視圖中,我實例化了我的API類的一個對象,這顯然不是非常乾燥。我也有一箇中間件,它向請求對象添加了一個或兩個有用的變量(我的中間件在鏈中最後運行)。

我想實例化中間件我的API類,然後將它傳遞給每個視圖作爲參數,即

def my_view(request, my_api_class_instance): 

,然後調用從中間件來看,是這樣的:

def process_view(self, request, view_func, view_args, view_kwargs): 
    my_api = api(some, args, here) 
    response = view_func(request, my_api, *view_args, **view_kwargs) 
    return response 

這似乎是一個快速簡單的方法來整理一些代碼並減少重複。對此有沒有什麼內在的壞處?

回答

1

如果你看看Django中間件documentation,你會看到;

如果process_view返回的HttpResponse對象,則Django不會打擾調用任何其它視圖或異常中間件,或相應的視圖;它會將響應中間件應用於該HttpResponse,並返回結果。

所以返回一個HttpResponse將跳過其他中間件類在這之下的這一般應避免除非你的中間件是最後一個在settings.MIDDLEWARE_CLASSES名單執行。

但是,您仍然可以將您的API對象綁定到傳遞給中間件的HttpRequest實例。這與AuhenticationMiddleware爲了填充request.user所做的是一樣的。

def APIMiddleware(object): 
    def process_request(self, request): 
     request.api = API(host, port, user, password, extra={"url": request.get_full_path()}) 
0

您可以使用中間件,但也有其他兩種可能性,兩者都更靈活。第一種是使用一個裝飾和包裝的看法:

@my_api_init_decorator 
def my_view(request, my_api): 
    ... 

這可以讓你明確選擇視圖,檢查用戶的授權或許可,你初始化你的API之前...

第二種解決方案是使用基於類的視圖並創建您自己的繼承視圖。

+0

這樣,開發人員最終可能不得不用新的裝飾器來包裝應用程序中的所有視圖,而這並不靈活且通用。 – ozgur

+0

取決於您的用例。如果所有視圖都需要api訪問權限,並且它永遠不會改變,那麼請使用中間件。如果有/你將不需要api訪問的視圖,那麼使用其中一種可能性會更好。它的方式非常靈活,您可以非常輕鬆地控制哪個視圖具有api訪問權限,哪個視圖不具有訪問權限。或者,您可以在api初始化之前檢查每個視圖的權限(其他事項)(當api init是一個昂貴的調用並且您希望最小化這些調用時有用)。 – Bruce

+0

這個問題說:「幾乎所有的視圖都與外部API進行一些交互」,所以中間件應該是首選的方法。 – ozgur

0

你可以改變view_kwargs中間件

class SomeMiddleware(object): 
    def process_view(self, request, view_func, view_args, view_kwargs): 
     view_kwargs['my_api'] = api(some, args, here) 
     return None 

def my_view(request, my_api): 
    # you can use you api there 
def my_view(request, args, my_api) 
    # you can use you api there 

document it's there 中間件返回None,Django將繼續處理這個請求,執行其它process_view()中間件。

但是,這隻適用於每個視圖函數都可以得到的關鍵字參數'myapi',否則會引發TypeError。

所以最好的方法是不要通過函數參數傳遞你的API,比如@ozgur通過請求傳遞你的API。

相關問題