我正在为大约10个模型建立一些抽象模型。我需要以某种方式使1字段不在抽象模型中声明,但必须在继承模型中声明。如何做到这一点?有什么方法可以使用NotImplementedError吗?
发布于 2012-10-21 07:54:08
如果可能的话,如果不深入研究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的模型继承一起工作。
发布于 2012-10-21 09:07:23
你为什么要这么做?公共字段不能在AbstractModel中声明的原因是什么??
如果您真的想这样做,请使用此处的说明:add methods in subclasses within the super class constructor
https://stackoverflow.com/questions/12993609
复制相似问题