【问题标题】:How do I satisfy "enforce_srid_coordinate" constraint with GeoDjango/PostGIS?如何使用 GeoDjango/PostGIS 满足“enforce_srid_coordinate”约束?
【发布时间】:2012-05-16 04:49:28
【问题描述】:

我正在使用 GeoDjango,并且有一个带有 PointField 的 Django 模型:

class ArchivrItem(models.Model):
    ...
    coordinate = models.PointField(srid=4326)

当我尝试使用纬度和经度插入新的 ArchivrItem 时,我收到此错误:

ERROR:  new row for relation "archivr_archivritem" violates check constraint "enforce_srid_coordinate"

我可以通过尝试这样做来避免 Django 并直接在 postgresql 中得到相同的错误:

INSERT INTO archivr_archivritem (coordinate) VALUES ('POINT(51.520667 -0.094833)');

我可能对 SRID 和点系统太天真和无知了……我错过了什么?谢谢。

更新:我应该添加约束是什么。对表的约束是:

"enforce_dims_coordinate" CHECK (st_ndims(coordinate) = 2)
"enforce_geotype_coordinate" CHECK (geometrytype(coordinate) = 'POINT'::text OR coordinate IS NULL)
"enforce_srid_coordinate" CHECK (st_srid(coordinate) = 4326)

【问题讨论】:

    标签: django postgresql postgis geodjango


    【解决方案1】:

    听起来您正在尝试通过这样做来添加新的存档项:

    item = ArchivrItem(coordinate='POINT(51.520667 -0.094833)')
    item.save()
    

    由于某种我不确定的原因,这没有得到正确的默认 SRID。但是,明确指定它应该可以工作,例如:

    from django.contrib.gis.geos import Point
    item = ArchivrItem(coordinate=Point(-0.094833, 51.520667, srid=4326))
    item.save()
    

    如果要匹配模型定义,我会说 srid 是可选的,但指定它并没有什么坏处,您可以查看是否只需使用对象方式即可修复它。 https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#creating-and-saving-geographic-models 有更多示例。

    [除此之外,请注意 POINT() 是 X 然后 Y,即 lon 然后 lat,而不是 lat/lon。如果使用“SRID=4326;POINT(-0.094833 51.520667)”扩展 WKT,您可以放入 SRID]

    【讨论】:

    • 嗯,我现在已经尝试了所有这些,但错误相同:item = ArchivrItem(coordinate=Point(5, 23))item = ArchivrItem(coordinate=GEOSGeometry('SRID=4326;POINT(5 23)'))item = ArchivrItem(coordinate=GEOSGeometry('POINT(5 23)', srid=4326))
    • 我已经成功地直接在 SQL 中管理它,方法是将其作为值插入:ST_SetSrid(ST_PointFromText('POINT(5 23)'),4326)
    • PointFromText 有一个 SRID 参数,不需要 SetSrid: postgis.org/docs/ST_PointFromText.html 。你能让它输出它试图运行的 SQL(那个页面有一个例子),看看它试图从 Django 做什么?
    • 啊,谢谢。嗯,所以 Django 正在记录这个:INSERT INTO "archivr_archivritem" ("coordinate") VALUES (ST_GeomFromEWKB('\x010100000000000000000014400000000000003740'::bytea)) RETURNING "archivr_archivritem"."id"; args=(<django.contrib.gis.db.backends.postgis.adapter.PostGISAdapter object at 0x111661d10>)
    • 使用 Django 1.2.3、Postgres 8.4,你给的所有三个版本在这里都没有错误,恐怕。我来自 Django 的 INSERT 包含一个包含 SRID 的 EWKB;你的上面没有并且仅相当于'POINT(5 23)'。如果没有更多的代码访问权限,我无法说出 srid 丢失的位置。
    【解决方案2】:

    在一位同事遇到相同问题后,我们似乎已将此问题归结为安装的 GEOS 版本的问题。使用有这个问题的版本,如果 p 是 django.contrib.gis.geos.Point,p.wkb 和 p.ewkb 返回相同的数据 - EWKB 缺少 SRID 信息。由于 Django 使用 EWKB 构造 SQL 以导入 PostGIS,这就是它失败的原因,无论创建的构造如何。

    我以前的 cmets 使用的是 Debian 的 3.2.0,它根本没有显示这个问题。 3.2.3 是此处显示此问题的版本。升级到 3.3.6 解决了这个问题(并且还测试了 3.3.3 这很好)。我会在今天晚些时候尝试其他版本,等我有更多时间尝试进一步追踪它。

    您可以通过以下方式查看您的 GEOS 版本:

    from django.contrib.gis.geos.libgeos import geos_version
    geos_version()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 1970-01-01
      • 2020-12-16
      • 2015-08-24
      • 2018-04-11
      相关资源
      最近更新 更多