Django:复合字段还是嵌入式类(比如JPA)?

2024-04-29 18:47:31 发布

您现在位置:Python中文网/ 问答频道 /正文

假设您必须对几个应该具有复合属性的类建模,比如维度宽度高度)或电话号码前缀号码扩展名)。在

在Java中(使用jpa2),我将创建一个维度类,并用@Embeddable对其进行注释。这会导致维度的字段(例如widthheight)嵌入到声明Dimensions类型属性的每个类中。在

如何在避免代码重复的同时用Django建模?创建一个单独的维度模型并用ForeignKey字段引用它是没有意义的。而且这些类没有足够的共同点来证明模型继承的合理性。在


Tags: 模型声明类型宽度高度属性电话号码java
1条回答
网友
1楼 · 发布于 2024-04-29 18:47:31

我想你可能是在想遗产问题。继承实际上是组合模型的推荐方法。下面是如何在Django中正确使用模型继承的示例:

class PhoneModelBase(model.Model):
    phone = models.CharField(max_length=16)
    ...

    class Meta:
        abstract = True

class PhoneModel(PhoneModelBase):
    # phone is here without typing it
    # the only restriction is that you cannot redefine phone here
    # its a Django restriction, not Python restriction
    # phone = models.CharField(max_length=12) # <= This will raise exception
    pass

所以它创建了一个模型PhoneModelBase,但是这里的关键是它使用class Meta和{}。在

这里有更多的幕后活动,以及一些Python概念的解释。我想既然你在问题中提到了Java,你就不知道它们了。如果Python的解释真的很混乱的话,你也不可能完全理解这些概念。你只需要知道使用abstact = True。这是官方文件:https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes。在

Meta中的Meta属性就是一个属性。它与类中的任何其他属性相同,只是它是一个类实例(请记住,在Python中,类和函数是一阶成员)。另外,Python有一个称为__metaclass__的东西,您可以将它添加到类中。__metaclass__定义了如何构建类的实例的方法。更多关于here。Django在创建模型类实例时使用了这些方法。在

因此,要创建PhoneModelBase类,下面是一个粗略的概述:

  • 当创建PhoneModelBase类的实例(类本身,而不是类-PhoneModelBase()的实例)时,由于继承而来自model.Model的{}将接管创建过程
  • __metaclass__中,Python调用创建实际类实例的函数,并将您尝试创建的类中的所有字段传递给它-PhoneModelBase。这将包括phoneMeta和您定义的任何其他字段
  • 它看到Meta属性,然后开始分析其属性。根据这些属性的值,Django将改变模型的行为
  • 它看到abstract属性,然后通过不将其存储在db中来更改它试图创建的类的逻辑PhoneModelBase

所以PhoneModelBase,尽管它的定义看起来非常类似于一个规则模型,但它不是一个规则模型。它只是一个抽象类,在其他模型中用作复合类。在

当其他模型从PhoneModelBase继承时,它们的__metaclass__将从基础模型复制属性,就像您手动键入这些属性一样。它不会是这样的外键。所有继承的属性都将成为模型的一部分,并且将位于同一个表中。在

希望所有这些都有意义。如果不是,您只需记住将Meta类与abstract = True一起使用。在

编辑

正如注释中所建议的,您还可以从多个基类继承。因此,您可以拥有PhoneModelBaseDimensionsModelBase,然后您可以从这两个(或更多)继承,所有基类的所有属性都将出现在模型中。在

相关问题 更多 >