就我个人而言,我是装饰者的狂热粉丝,这是一个并不特定于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