就我個人而言,我是裝飾者的狂熱粉絲,這是一個並不特定於Django的python特性。裝飾器是高級函數之上的完美語法糖,它們對於減少視圖中的樣板文件尤其有用 - 您可以快速定義一個通用包裝器函數,在該函數中可以將重複代碼輕鬆重複使用並且方便停止重構。
向他們展示可能比向他們解釋他們如何工作更容易。這裏是一個簡化的視圖例如:
def listpage(request):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
def itemlist_tags(request, tags):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
...但後來說,你想使這些頁面要求用戶登錄時,可能會添加像這樣登錄代碼:
def listpage(request):
if not request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
def itemlist_tags(request, tags):
if not request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
..即使對於一個人爲的例子,它開始變得明顯更大和重複。你可以讓你的功能與裝飾再次苗條,像這樣:
從裝飾進口裝飾
@decorator
def loginrequired(f, request, *args, **kwargs):
if request.user.is_authenticated():
return f(request, *args, **kwargs)
else:
return HttpResponseRedirect("/")
@loginrequired
def listpage(request):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.filter(visible=True).order_by("-modifydate")
}))
@loginrequired
def itemlist_tags(request, tags):
return HttpResponse(render_to_string("itemlist.html", {
"items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
}))
@loginrequired
def another_such_function(request):
(...)
@loginrequired
def and_again(request):
(...)
會發生什麼是裝飾功能在函數定義的時間執行。在我的例子中,'f'是一個代表裝飾器應用到的函數的對象,您可以以無數的方式操縱它。
這需要decorator library,它可以在PyPI上免費獲得,就像許多好的python缺點一樣。
你不需要這個庫來編寫裝飾函數,但它是有幫助的,特別是在開始時。他們可以做更多 - 任何可調用的可以是裝飾器;你可以修飾類方法並截取self
變量;裝飾可以鏈接起來,就像這樣:
@second
@first
def originalfunction(*args):
(...)
我會離開,你可以用這種簡單的高階函數manpipulation做探索適合你,應該這個概念激起你的食慾。我還有更多的例子,對於你或任何其他好奇的新Python愛好者。祝你好運。
順便說一下,第二個假視圖中的'tagged()'函數不是拼寫錯誤;它是我寫給django-tagging應用程序的一個簡化的界面,也是以樣板文件縮減的名義編寫的,這個好奇將會在這裏找到:http://www.djangosnippets.org/snippets/1942/ – fish2000 2010-03-20 21:58:31
非常有幫助,謝謝,裝飾者似乎對我有很多額外的用途。 – neopickaze 2010-03-21 19:15:50