我为大约10个模型构建了一些抽象模型。我需要以某种方式使得1字段不在抽象模型中声明,但必须在继承模型中声明。
怎么做?有没有办法使用NotImplementedError
?
答案 0 :(得分:3)
如果可能的话,我担心没有一种简单的方法可以实现这一目标,而无需深入研究Django。
主要原因是Django中的Field
name "hiding" is not permitted。这意味着如果你想在基本抽象类中声明一个Field
实例的抽象属性,你将无法在子类中重写它,这与普通的Python类继承范例相反。引用文档:
在普通的Python类继承中,子类允许覆盖父类的任何属性。在Django中,不允许使用Field实例的属性(至少目前不是这样)。如果基类有一个名为author的字段,则无法在从该基类继承的任何类中创建另一个名为author的模型字段。
在父模型中覆盖字段会导致在初始化新实例(指定在Model。 init 中初始化哪个字段)和序列化等方面存在困难。这些是普通Python类继承不必以完全相同的方式处理的特性,因此Django模型继承和Python类继承之间的区别不是任意的。
此限制仅适用于Field实例的属性。如果您愿意,可以覆盖正常的Python属性。它也只适用于Python看到的属性名称:如果您手动指定数据库列名,则可以在子表和祖先模型中出现相同的列名,以进行多表继承(它们是列在两个不同的数据库表中。)
如果覆盖任何祖先模型中的任何模型字段,Django将引发FieldError。
但是,如果该属性不是Field
实例(尽管不太可能),您将能够通过使用@property
装饰器完全达到您想要的效果。这样的事情应该有效:
class Person(models.Model):
def __init__(self, *args, **kwargs):
super(Person, self).__init__(*args, **kwargs)
self.last_name
first_name = models.CharField(max_length=30)
@property
def last_name(self):
raise NotImplementedError
class Meta:
abstract = True
class Student(Person):
home_group = models.CharField(max_length=5)
last_name = "Doe" # "models.CharField()" will not work!
class BadStudent(Person):
home_group = models.CharField(max_length=5)
# "NotImplmentedError" will be raised when instantiating BadStudent()
您可能还想查看abc.abstractproperty
。我不确定它如何与Django的模型继承一起工作。
答案 1 :(得分:0)
你为什么要这样做?哪些是在AbstractModel中无法声明公共字段的原因?
如果您真的想这样做,请使用以下说明: add methods in subclasses within the super class constructor