Django - 如何实现字段的实现?

时间:2012-10-20 23:30:56

标签: python django django-models

我为大约10个模型构建了一些抽象模型。我需要以某种方式使得1字段不在抽象模型中声明,但必须在继承模型中声明。 怎么做?有没有办法使用NotImplementedError

2 个答案:

答案 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