代码之家  ›  专栏  ›  技术社区  ›  Horai Nuri

django 2.1-“functools.partial”对象没有属性“uu name_uuuu”

  •  1
  • Horai Nuri  · 技术社区  · 6 年前

    我最近将django从2.0.7升级到2.1.1,出现了一个新的错误,我得到了这个错误。 'functools.partial' object has no attribute '__name__' .

    我想知道如果我的修复是正确的,以及是什么导致了这个新错误的发生,我在django发行说明中找不到与这个问题相关的任何内容,也许我错过了。

    装饰家

    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
    

    如何使用, VIEW :

    @method_decorator(auth0_login_required, name='dispatch')
    class Dashboard(View):
        ...
    

    为了我刚移除的修复 wrap.__name__ = function.__name__ 但我不确定它是否会破坏其他东西。

    有人能解释吗?

    1 回复  |  直到 6 年前
        1
  •  6
  •   Martijn Pieters    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 对象正确(或者更确切地说,它可以处理 功能工具.部分 对象没有 __name__ 属性)。

    很好,包装的 functools.partial() 在上找到的对象 View 班级没有 第二代 属性,不好的是,即使在装饰具有该属性的函数时,也不会复制该属性。如果你不想使用 @ WRAP() 您必须手动复制属性并自己处理异常:

    try:
        wrap.__name__ = function.__name__
    except AttributeError:
        pass
    try:
        wrap.__doc__ = function.__doc__
    except AttributeError:
        pass
    

    但要考虑到这不会复制 __qualname__ , __module__ __annotations__ 属性,不处理在上设置的任何自定义属性 function (其他装饰师可能依赖的)。 @functools.wrapps()函数 会处理所有这些,而且它会设置 __wrapped__ decorator包装函数的属性 would let you unwrap the decorator again .