2011-07-17 106 views
1

我的應用程序中有以下裝飾器,它檢查當前用戶是否創建了任何位置對象,並將它們重定向到另一個URL(如果它們沒有)。Django將模型名稱作爲參數傳遞給裝飾器

def location_required(f): 
    def wrap(request, *args, **kwargs): 
     locations = Location.objects.filter(user=request.user) 
     if locations.count() == 0: 
      return HttpResponseRedirect("/") 
     return f(request, *args, **kwargs) 
    wrap.__doc__=f.__doc__ 
    wrap.__name__=f.__name__ 
    return wrap 

我想爲其他模型有類似的功能。我不希望創建多個裝飾器,而是希望能夠將模型名稱作爲參數傳遞(也可能是重定向到的url)。

這是可能的,我需要做些什麼改變?

任何意見將不勝感激。

謝謝。

回答

1

絕對有可能。它可能最終看起來像下面這樣(未經)代碼:

def object_required(model_class, redirect_url): 
    def location_required(f): 
     def wrap(request, *args, **kwargs): 
      locations = model_class.objects.filter(user=request.user) 
      if locations.count() == 0: 
       return HttpResponseRedirect(redirect_url) 
      return f(request, *args, **kwargs) 
     wrap.__doc__=f.__doc__ 
     wrap.__name__=f.__name__ 
     return wrap 
    return location_required 

所有我在這裏所做的是增加包裝的另一層。您的原始裝飾器自定義傳入的函數f。我的外層自定義您的裝飾器。你會以同樣的方式使用它:在處理模型類另一個函數包裝現有裝飾的

@object_required(Location, '/') 
def my_view_func(request) 
    #your view code 
+0

感謝您的幫助! – Dan

2

加雷的做法和重定向URL是否正確。我建議以下的小變化:的

  • 使用exists(),而不是比較count()
  • 使用django.utils.functional.wraps更新包函數,而不是手動設置__name____doc__
  • wrap函數中的locations變量被錯誤命名,現在它可能是任何模型實例。

這給:

from django.utils.functional import wraps 

def object_required(model_class, redirect_url="/"): 
    # model_class and redirect_url are available to all inner functions 
    def decorator(f): 
     # this is called with f, the function being decorated 
     def wrapper(request, *args, **kwargs): 
      # this is called each time the real function is executed 
      instances = model_class.objects.filter(user=request.user) 
      if not instances.exists(): 
       return HttpResponseRedirect(redirect_url) 
      return f(request, *args, **kwargs) 
     return wraps(f)(wrapper) 
    return decorator 

在視圖:

@object_required(Location, "/") 
def my_view_function(request): 
    # your view code 
+0

謝謝。在整個項目中重用的最佳位置是哪裏?一個單獨的應用程序僅用於裝飾器功能是否過分矯枉過正? – Dan

+0

也許創建一個'utils'應用程序,並將裝飾器放在'utils.decorators'中。 – Alasdair