Django 模型条件关系

Django Model conditional relationship

新手问题:Django + Postgres + PostGIS

我正在尝试在 Django 中设置一个项目模型,该模型需要根据其几何类型有条件地与几何模型相关。几何类型是:点、线或多边形。问题是我如何在项目模型中定义这种关系,这样我就不必在同一个 table 中保存不同的几何类型(因此有 3 个不同的几何模型)

=======================这是我的模型================== ==========

PRJ_GEOM = (
         (1, "point"),
         (2, "line"),
         (3, "polygon")
  )

class Project(models.Model):
    name = models.CharField(max_length=20)
    project_geom_type = models.IntegerField(choices=PRJ_GEOM)
    project_geometry = models.OneToOneField( ????) # I am stuck here - how do I express this conditional relationship which depends on project_geom_type

#几何模型

class Project_Point_Geom(models.Model):
      project = models.OneToOne(Project, on_delete=models.CASCADE, related_name='project_point')
      point = models.PointField()

class Project_Line_Geom(models.Model):
      project = models.OneToOne(Project, on_delete=models.CASCADE, related_name='project_line')
      line = models.LineStringField()

class Project_Polygon_Geom(models.Model):
      project = models.OneToOne(Project, on_delete=models.CASCADE, related_name='project_polygon')
      polygon = models.PolygonField()

您的 Project 模型不需要 project_geometry 字段。您只需要使用 OneToOne 字段将不同的几何模型与项目相关联。 Django 自动为 ForeignKeyManyToManyOneToOne 关系创建反向关系。您的 类 看起来像这样:

class Project(models.Model):
    name = models.CharField(max_length=20)

class Point_Geo(models.Model):
      project = models.OneToOne(Project) # truncated for example
      point = models.PointField()

class Line_Geo(models.Model):
      project = models.OneToOne(Project) # truncated for example
      line = models.LineStringField()

class Polygon_Geo(models.Model):
      project = models.OneToOne(Project) # truncated for example
      polygon = models.PolygonField()

当你有一个 Project 实例时,你可以像这样沿着反向关系返回:

project = Project.objects.get(id=1)
point = project.point_geo.point

要查询具有点几何的所有项目,您可以查询:

projects_with_points = Project.objects.exclude(point_geo=None)

其实你只需要一个模型。所有几何字段都派生自 GeometryField,因此您可以使用它来存储它的子 类。

PRJ_GEOM = (
         (1, "point"),
         (2, "line"),
         (3, "polygon")
  )

class Project(models.Model):
    name = models.CharField(max_length=20)
    project_geom_type = models.IntegerField(choices=PRJ_GEOM)
    project_geometry = models.GeometryField()

就是这样!一个模型,一个 table 而不是四个,这样更容易维护。并且由于去掉了关系字段,数据略小