我有一个父类,应该由将成为Django模型的子类继承。子类都具有一个公共属性x
,因此它应该是父类的抽象属性。子代之间的区别在于该属性是Django模型属性还是直接设置。
class A(Model, metaclass=abc.ABCMeta):
class Meta:
abstract = True
@property
@abc.abstractmethod
def x(self):
pass
class B(A):
x = "hello"
class C(A):
x = models.CharField(max_length=100, default='defaultC')
class D(A):
x = models.CharField(max_length=50, default='defaultD')
因此,在我的示例中,对于某些子类,属性x
是已知的,但在其他情况下,则需要选择该属性。但是有一件事是,类A
的所有后代都需要一个x
属性,因为它是一个公共属性,必须由任何后代定义。
问题是,如果我实例化C
或D
的类,则会得到以下信息:
TypeError: Can't instantiate abstract class C with abstract methods x
我认为问题出在Django元类的幕后。它删除了所有django模型属性,并用延迟的属性或某些属性替换了它们,因此该属性从未真正定义过。
我可以尝试将模型属性上移到类A
上,并根据需要让子类作为静态值覆盖:
class A(Model, metaclass=abc.ABCMeta):
class Meta:
abstract = True
x = models.CharField(max_length=100)
class B(A):
x = "hello"
class C(A):
x = models.CharField(max_length=100, default='defaultC')
class D(A):
x = models.CharField(max_length=50, default='defaultD')
我的问题是,这感觉不太抽象。 C
和D
仍需要覆盖x
来设置其默认值和最大长度。还让我担心的是,通常在代码中使用类A
的人们会假设属性x
将是django数据库字段;相反,有时它可以是静态字符串值。
这里理想的方法是什么?我真的很想实现我的第一个例子。