菊花链式Python / Django自定义装饰器好吗?并传递与收到的论点不同的论点?
我的许多Django视图功能都以完全相同的代码开始:
@login_required
def myView(request, myObjectID):
try:
myObj = MyObject.objects.get(pk=myObjectID)
except:
return myErrorPage(request)
try:
requester = Profile.objects.get(user=request.user)
except:
return myErrorPage(request)
# Do Something interesting with requester and myObj here
仅供参考,这是urls.py文件中的相应条目的样子:
url(r'^object/(?P<myObjectID>\d+)/?$', views.myView, ),
在许多不同的视图函数中重复相同的代码根本不是DRY。我想通过创建一个装饰器来对其进行改进,该装饰器将为我完成此重复性工作并使新的视图函数更整洁,如下所示:
@login_required
@my_decorator
def myView(request, requester, myObj):
# Do Something interesting with requester and myObj here
所以这是我的问题:
1)是的,链接装饰器是有效的,因为其他答案已经指出。好的样式是主观的,但是我个人认为这会使您的代码更难为他人阅读。熟悉Django但不熟悉您的应用程序的人在使用您的代码时需要保持头脑清醒。我认为坚持框架约定以使您的代码尽可能可维护非常重要。
2)答案是肯定的,将不同的参数传递给包装函数在技术上是可以的,但是请考虑一个简单的代码示例,说明其工作方式:
def decorator1(func):
def wrapper1(a1):
a2 = "hello from decorator 1"
func(a1, a2)
return wrapper1
def decorator2(func):
def wrapper2(a1, a2):
a3 = "hello from decorator 2"
func(a1, a2, a3)
return wrapper2
@decorator1
@decorator2
def my_func(a1, a2, a3):
print a1, a2, a3
my_func("who's there?")
# Prints:
# who's there?
# hello from decorator 1
# hello from decorator2
我认为,任何阅读此书的人都必须是一个心理运动员,才能在装饰器堆栈的每个级别上保留方法签名的上下文。
3)我将使用基于类的视图并重写dispatch()
方法来设置实例变量,如下所示:
class MyView(View):
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
self.myObj = ...
self.requester = ...
return super(MyView, self).dispatch(*args, **kwargs)
该dispatch
方法称为您的get()/post()
方法。从Django文档中:
as_view入口点创建您的类的实例并调用其dispatch()方法。dispatch会检查请求以确定它是否是GET,POST等,并将请求转发给匹配的方法(如果已定义)
然后,您可以在您的get()
和/或post()
视图方法中访问这些实例变量。这种方法的优点是您可以将其提取到基类中,并在任意数量的View子类中使用它。由于这是标准继承,因此它在IDE中的可追溯性也更高。
有关get()
请求外观的示例:
class MyView(View):
def get(self, request, id):
print 'requester is {}'.format(self.requester)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句