我正在使用现有的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
答案 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中删除该类,因为它已经在调用装饰器时创建(因此已经调用了元类) )。