【问题标题】:How to create abstract model in Django?如何在 Django 中创建抽象模型?
【发布时间】:2020-02-15 23:08:13
【问题描述】:

我是 Django 框架的新手,在我的项目中我有一个名为 Layer 的模型。

class Layer(models.Model):
    name = models.CharField(max_length=255)

我希望层与称为“几何”的抽象模型建立关系,更具体地说,一层应该有一个或没有几何,一个几何应该由一层拥有。

问题是我有几何类型,它们都有不同的属性,所以我决定创建多个几何:

class Circle(models.Model):
    radius = models.CharField(max_length=255)

class Rectangle(models.Model):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

我想要一个数据结构,其中两个模型属于同一类型(几何)。我想调用 layer.geometry 并能够得到一个圆形或一个矩形,或者一个十字形等等。那可能吗?数据库的形状将如何? Django 是要创建两个不同的表还是一个具有合并属性的表?

提前致谢

【问题讨论】:

  • 您不能与 abstract 模型建立关系。您可以对它进行子类化,但模型仍然有一个表。应该这样做以引入 FOREIGN KEY 约束以防止引用不存在的约束。

标签: django django-models django-rest-framework


【解决方案1】:

Django 支持继承,虽然它不是很常见。因此,您可以创建一个模型Geometry,并让CircleRectangle 从中继承:

class Geometry(models.Model):
    pass

class Circle(Geometry):
    radius = models.CharField(max_length=255)

class Rectangle(Geometry):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

我们还可以通过以下方式与Geometry 类建立ForeignKey(或其他关系):

class Layer(models.Model):
    name = models.CharField(max_length=255)
    geometry = models.ForeignKey(Geometry, on_delete=models.CASCADE)

Django 将进行迁移,为 SQL 数据库创建 GeometryCircleRectangle 的表。 CircleRectangle 模型将在名为 geometry_ptr_idGeometry 的表中隐含 OneToOneRelation,因此它指的是父代。

有关详细信息,请参阅Multi-table inheritance in the documentation 部分。

【讨论】:

  • 对,完美解释。 Django 允许抽象类,但你不能引用它们。
  • 这是否意味着我无法运行 layer.geometry?甚至不在 django-rest-framework 的 json 响应中?那么如果一个图层有一个圆,它会被称为圆而不是几何?
【解决方案2】:

虽然您可以将CirleRectangle 模型与ForeignKeyOneToOneField 关联,但您可以选择为Geometry 模型创建AbstractModel

class Geometry(models.Model):
    id = models.IntegerField()

    class Meta:
        abstract = True

class Circle(Geometry):
    radius = models.CharField(max_length=255)

class Rectangle(Geometry):
    height = models.CharField(max_length=255)
    width = models.CharField(max_length=255)

因此,CircleRectangle 模型都将具有来自 Geometry 模型的 id 字段,但在您的数据库中只有 2 个表。但是,您将无法在Geometry 模型中查询。

如果您需要显式查询Geometry 模型,请选择ForeignKeyOneToOneField 选项。如果不是,我认为abstract 模型是一种更清洁的方法。

From Django Docs: 通常,您只想使用父类来保存您不想为每个子模型输入的信息。这个类永远不会被孤立地使用,所以抽象基类是你所追求的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2016-04-03
    相关资源
    最近更新 更多