如何在Python中创建一个类似Django的抽象基类的类?

时间:2010-12-27 20:12:25

标签: python django abstract metaclass

我正在使用现有的Django库,我正在创建一个我想要抽象的类。

我们说有问题的课程是BaseFoo

目前,该实现具有基类BaseFoo

每次创建扩展BaseFoo的类时,元类都会将其添加到类列表中。它明确地不通过对类名进行硬编码测试来添加BaseFoo

    if name not in ('BaseFoo',):
        class_list.append(new_cls)

我希望能够写出类似的内容:

class MyBaseFoo(BaseFoo):
    class Meta:
        abstract = True

让元类跳过所有抽象的BaseFoo个对象。所以我想我想知道Django如何对模型做同样的事情,以及是否有一种简单,优雅的方式来做到这一点。

我已经查看了Django用于定义模型的一些代码,但我可以使用一些指针。此外,如果有一种更简单的方法可以做到这一点而不必使用class Meta我也会对此持开放态度。

请注意,我对此解决方案并不感到特别激动:

class MyBaseFoo(BaseFoo):
    abstract = True

class ActualFoo1(MyBaseFoo):
    abstract = False

class ActualFoo2(MyBaseFoo):
    abstract = False

1 个答案:

答案 0 :(得分:3)

在具体类中不需要将abstract设置为False - 仅在抽象类中设置此设置就足够了:

class_list = []
class CollectSubclasses(type):
    def __new__(cls, name, bases, attrs):
        abstract = False
        if attrs.get('abstract', False):
            abstract = True
            del attrs['abstract']
        res = super(CollectSubclasses, cls).__new__(cls, name, bases, attrs)
        if not abstract:
            class_list.append(res)
        return res

class BaseFoo(object):
    __metaclass__ = CollectSubclasses
    abstract = True

class Concrete1(BaseFoo):
    pass

class Abstract(BaseFoo):
    abstract = True

class Concrete2(Abstract):
    pass

print class_list

另一种选择可能是Python 2.6中的类装饰器,但是,您需要从@abstract装饰器中的class_list中删除该类,因为它已经在调用装饰器时创建(因此已经调用了元类) )。