【问题标题】:Django Model conditional relationshipDjango 模型条件关系
【发布时间】:2017-01-24 02:34:52
【问题描述】:

新手问题:Django + Postgres + PostGIS

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

【问题讨论】:

    标签: django django-models postgis geodjango


    【解决方案1】:

    实际上你只需要一个模型。所有几何字段都派生自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()
    

    就是这样!一个模型,一个表而不是四个更容易维护的表。并且数据稍微小一些,因为关系字段被消除了。

    【讨论】:

    • 我假设这将导致不同的几何类型保存在名为 project_geometry 的同一字段中。根据我的 GIS 经验,我知道这不是一个好主意,但也许没关系。有什么线索吗?有关系吗?
    • 是的,不同的几何图形保存在同一个字段类型中并不重要。
    • 这很棒。想知道这是否会对空间查询的结果产生任何影响 - 比如说我要查询多边形内的所有项目 - 我知道点几何会返回一个集合,对于线条和多边形,结果会是什么样子? postgis 是否执行交集并返回边界多边形内的所有几何?
    • 如果您询问 __within 或 __dwithin postgis 查询,是的,它们适用于任何几何类型。您的 project_geom_type 列告诉您您的类型是什么。但即使这样也不是真正需要的,因为可以通过检查几何字段本身来确定类型。
    【解决方案2】:

    您的 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)
    

    【讨论】:

    • 没有该字段我怎么知道项目的几何类型?假设我有一个项目 ID,在最坏的情况下我不需要 3 个查询来确定它的几何形状吗?
    • 您可以通过检查是否存在任何反向关系来查询它,但我主要只是为了简化示例。
    猜你喜欢
    • 2020-11-01
    • 2019-07-30
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2016-06-16
    相关资源
    最近更新 更多