I recently upgraded Django from 2.0.7 to 2.1.1, a new error occurs in which I get this error \'functools.partial\' object has no attribute \'__name__\'
.
I\
Rather than manually copy things across, use the @functools.wraps() decorator to handle this for you:
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
The @wraps()
decorator (via the functools.update_wrapper() function it calls knows how to handle functools.partial
objects correctly (or rather, it can handle the fact that functools.partial
objects have no __name__
attribute).
It's fine that the wrapped functools.partial()
object found on the View
class doesn't have a __name__
attribute, what's not fine is that you then don't copy that attribute at all even when you are decorating functions that do have the attribute. If you don't want to use @wraps()
you'd have to manually copy the attribute across and handle the exception yourself:
try:
wrap.__name__ = function.__name__
except AttributeError:
pass
try:
wrap.__doc__ = function.__doc__
except AttributeError:
pass
but take into account that this doesn't copy the __qualname__
, __module__
and __annotations__
attributes, doesn't handle any custom attributes set on function
(which other decorators might rely on). @functools.wraps()
does take care of all of those, plus it sets the __wrapped__
attribute on the decorator wrapper function that would let you unwrap the decorator again.