首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django -如何使需要实现的字段?

Django -如何使需要实现的字段?
EN

Stack Overflow用户
提问于 2012-10-21 07:30:56
回答 2查看 1K关注 0票数 3

我正在为大约10个模型建立一些抽象模型。我需要以某种方式使1字段不在抽象模型中声明,但必须在继承模型中声明。如何做到这一点?有什么方法可以使用NotImplementedError吗?

EN

回答 2

Stack Overflow用户

发布于 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装饰器来实现您想要的效果。像这样的东西应该是有效的:

代码语言:javascript
运行
复制
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的模型继承一起工作。

票数 4
EN

Stack Overflow用户

发布于 2012-10-21 09:07:23

你为什么要这么做?公共字段不能在AbstractModel中声明的原因是什么??

如果您真的想这样做,请使用此处的说明:add methods in subclasses within the super class constructor

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12993609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档