【问题标题】:Django PointField with geography=True can't save data: SQL function errorgeography=True 的 Django PointField 无法保存数据:SQL 函数错误
【发布时间】:2021-02-15 06:38:45
【问题描述】:

我有一个安装了 GIS 扩展的 Django 3.1.2PostgreSQL 12PostGIS 3

在我的模型中,我尝试使用 PointFieldgeography=True 来存储真实世界坐标:

location = models.PointField(geography=True, srid=4326, blank=False, null=False, verbose_name=_("Lat/Lon coordinates"))

在管理菜单中,我使用 OSMWidget 输入坐标:

location = forms.PointField(widget=forms.OSMWidget(attrs={'map_width': 800, 'map_height': 500, 'default_zoom': 15}))

保存后,Django 会遇到以下 SQL 错误:

INSERT INTO "challenges_point" ("track_id", "sortkey", "name", "location") VALUES (15, 10, 'Start', ST_Transform(ST_GeogFromWKB('\x...'::bytea), 4326)) RETURNING "challenges_point"."id";
ERROR:  function st_transform(geography, integer) does not exist
LINE 1: ...", "location") VALUES (15, 10, 'Start', ST_Transfo...
                                                   ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

ST_Transform() 用于转换几何点(如果geography=False 用于PointField,则用作数据类型)。但我不确定要使其适用于地理环境需要什么。

【问题讨论】:

  • 您可以尝试将 srid=4326 添加到您的表单域吗?
  • 您的意思是:“forms.OSMWidget(attrs={'srid': 4326, 'map_width': 800 ...”?我添加了,但结果相同。

标签: django gis geospatial postgis


【解决方案1】:

由于您覆盖了 PointField,它没有设置 srid,并且 ST_Transform 用于将几何图形转换为正确的空间参考。

有几种方法可以正确更改小部件,但我会用您当前的代码为您提供最简单的一种:

location = forms.PointField(
    srid=4326,
    widget=forms.OSMWidget(
        attrs={'map_width': 800, 'map_height': 500, 'default_zoom': 15}
    )
)

其他方式有:

  • 扩展Model.formfield()并将form_class.widget更改为OSMWidget。
  • 实现ModelAdmin.formfield_overrides 并仅指定小部件属性。这是有效的,因为您不必覆盖整个字段,而只需覆盖特定属性,默认值将来自上面的 Model.formfield(),它正确设置了 srid。
  • 使用ModelForm's meta class 仅覆盖小部件。工作方式与以前类似。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-18
    • 2011-02-27
    • 2016-04-29
    • 2011-12-01
    • 2020-02-13
    • 2016-02-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多