我最近将Django从2.0.7升级到2.1.1,出现一个新错误,我收到此错误'functools.partial' object has no attribute '__name__'
。
我想了解我的修复程序是否正确以及导致此新错误发生的原因,我在django发行说明中找不到与此问题相关的任何内容,也许我错过了。
decorators.py
def auth0_login_required(function):
def wrap(request, *args, **kwargs):
if request.isAuthenticated or request.user.is_staff:
pass
else:
raise Http404()
return function(request, *args, **kwargs)
wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__ # ERROR HERE
return wrap
使用方式, views.py :
@method_decorator(auth0_login_required, name='dispatch')
class Dashboard(View):
...
对于此修复程序,我刚刚删除了wrap.__name__ = function.__name__
,但不确定是否会破坏其他功能。
有人可以解释吗?
答案 0 :(得分:6)
使用@functools.wraps()
decorator帮您完成此任务,而不是手动复制内容:
from functools import wraps
def auth0_login_required(function):
@wraps(function)
def wrap(request, *args, **kwargs):
if request.isAuthenticated or request.user.is_staff:
pass
else:
raise Http404()
return function(request, *args, **kwargs)
return wrap
@wraps()
装饰器(通过functools.update_wrapper()
function it calls知道如何正确处理functools.partial
对象(或者说,它可以处理functools.partial
对象没有{{1 }}属性。
在__name__
类上找到的包装的functools.partial()
对象没有View
属性是没有问题的,那是不好的,那就是您根本不复制该属性即使在装饰确实具有该属性的函数时也是如此。如果您不想使用__name__
,则必须手动复制属性并自己处理异常:
@wraps()
,但要考虑到这不会复制try:
wrap.__name__ = function.__name__
except AttributeError:
pass
try:
wrap.__doc__ = function.__doc__
except AttributeError:
pass
,__qualname__
和__module__
属性,也不处理__annotations__
上设置的任何自定义属性(其他装饰者可能依赖)。 function
确实会处理所有这些问题,此外,它还会在装饰器包装函数would let you unwrap the decorator again上设置@functools.wraps()
属性。