0

从 Django 1.5 开始,现在内置了对 User 模型的子类化以添加自定义功能的支持,但仍然存在一些兼容性方面的考虑,这意味着我不希望这样做。在 1.5 之前,子类化是一个很大的麻烦。但是,我需要一些功能,特别是以方法 .full_name() 的形式。这将返回first + " " + middle + " " +last用户的名称。更一般地说,它只在适当的地方放置空格,并且可以处理中间名,但不要求模型包含中间名。

现在,而不是子类 User,我只是在我的 models.py 的顶部有以下内容:

def full_name(self):                                    # Here's a useful full_name method
    '''Return the full name of an object, or else an empty string. Can be applied to objects with first_name, last_name and optionally middle_name fields'''
    fullname = self.first_name
    try:
        self.middle_name
    except AttributeError:                          # this type of object might not have a middle_name field
        pass
    else:                                           # If it has a middle_name field, append it with a conditional space
        if(self.first_name and self.middle_name):
            fullname += " "
        fullname += self.middle_name
    if(fullname and self.last_name):                # if fullname has stuff in it now, we'll need a space.
            fullname += " "
    fullname += self.last_name
    return fullname
User.full_name = full_name                              # Bless the User model with our full_name function

总的来说,我对 Python 比较陌生,所以我很高兴发现它可以工作。通过对其他几个模型使用相同的函数,我节省了一些时间(稍后在 models.py 中的类定义中简单地描述 full_name = full_name)。也许现在 middle_name 功能更有意义 - 其他模型有中间名。

我的问题是,这种做法与子类化有什么本质上的错误坏处吗?大概主要的缺点是我不能以这种方式将字段添加到模型中。但就是这样吗?此方法添加似乎在应用程序的其余部分以及导入用户的任何其他模块中持续存在(具体而言,模板按预期工作)。

基本上,我认为这是解决我需要更多功能的问题的一种非常聪明和优雅(虽然我肯定不是新奇)的方式,但它会回来咬我吗?

更多细节:我问的一个原因是我有一些具有关系的用户角色(我们称他们为 Painter、Clerk 和 Manager)models.ForeignKey(User, blank=True)。例如,User.painter 可能会返回 Painter 角色,但如果用户实际上不是画家,它也可能引发 ObjectNotFound 异常。我不想用 try: except: 语句乱扔我的代码,我想扩展我对上述想法的使用,例如向 User 添加 .is_painter() 和 .is_manager() 方法,这样我就可以简单地在if 语句而不是做很少的尝试:除了:到处乱七八糟。

4

1 回答 1

1

这称为猴子修补。正如您可能已经从它不太讨人喜欢的名字中了解到的那样,并不总是受到好评。在 Python 社区中,这不是一种常见的技术,通常保留在没有其他选择的情况下。由于您有一个适当的接口(子类化)来实现您想要的,因此最好避免。

Monkey patching 可能很脆弱,如果你正在修改的模块在你下面发生变化,就会破坏。其他人以后可能很难修改/调试,因为代码实际位于何处并不总是很明显。

也就是说,如果它已经存在并且正在工作,您可以保留它。没有人会追踪您并为此在黑暗的小巷中殴打您。

于 2013-03-20T21:09:05.453 回答