geography=True 的 Django PointField 无法保存数据:SQL 函数错误
Django PointField with geography=True can't save data: SQL function error
我有一个 Django 3.1.2
安装了 GIS 扩展,PostgreSQL 12
和 PostGIS 3
。
在我的模型中,我尝试使用 PointField
和 geography=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
,则用作数据类型)。但我不确定需要什么才能使其适用于地理。
由于您覆盖了 PointField,因此它没有设置 srid,并且 ST_Transform 用于将 geom 转换为正确的空间参考。
有多种方法可以正确更改小部件,但我将使用您当前的代码为您提供最简单的方法:
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
并且只指定widget属性。这是可行的,因为您不必覆盖整个字段,而只需覆盖特定属性,默认值将来自上面的 Model.formfield()
,它正确设置了 srid。
- 使用 ModelForm's meta class 仅覆盖小部件。与之前的工作方式类似。
我有一个 Django 3.1.2
安装了 GIS 扩展,PostgreSQL 12
和 PostGIS 3
。
在我的模型中,我尝试使用 PointField
和 geography=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
,则用作数据类型)。但我不确定需要什么才能使其适用于地理。
由于您覆盖了 PointField,因此它没有设置 srid,并且 ST_Transform 用于将 geom 转换为正确的空间参考。
有多种方法可以正确更改小部件,但我将使用您当前的代码为您提供最简单的方法:
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
并且只指定widget属性。这是可行的,因为您不必覆盖整个字段,而只需覆盖特定属性,默认值将来自上面的Model.formfield()
,它正确设置了 srid。 - 使用 ModelForm's meta class 仅覆盖小部件。与之前的工作方式类似。