我正在使用现有的 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
请您参考如下方法:
没有必要在具体类中将 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 中删除该类,因为它已经在装饰器被调用时创建(因此元类已经被调用).
