为什么在尝试更新 geoDjango Point objects 时没有保存任何内容?
Why is nothing being saved when trying to update geoDjango Point objects?
已解决:查看我自己的回答以获得解释。
我正在写一个 API 来帮助我在需要时维护我的数据库。
我的 API 的一个功能是更新所有相关 object 的特定 geoDjango Point
字段,这要归功于我的模型的专用方法(这是非常无用的重新编辑 EDIT 1,见下文)。
我一直面临的问题如下:在多个 object 上调用该方法时似乎没有任何内容保存到数据库中,即使对 save
方法的调用似乎在浏览 object 时工作。
参见 EDIT 2,我发现这个问题是 geoDjango Point
objects 特有的(其他所有内容都按预期更新)。
下面是我的模型:
models.py
class Location(geoModels.Model):
coord_field = geoModels.PointField(blank=True, null=True)
valTest = models.CharField(max_length=100, default="tagada") # only used to understand why coord_field can't be updated properly
def update_coord_field(self):
# some stuff is being done
self.coord_field = Point(
newLong,
newLat,
srid=3857 # I am trying to update that value
)
# nothing more
由于 Google 地图 API,正在生成 newLong
和 newLat
。
由于 Google 地图似乎与 SRID 3857
一起工作,而 GeoDjango 在创建新的 Point
时默认使用 SRID 4326
,我想强制 self.coord_field
的 SRID 为 SRID 3857
(我一直面临不一致的距离演算,所以我正在尝试使用 SRID 来解决这个问题)。
现在这是我的脚本:
script.py
from MyApp import models as MyAppModels
def update_all_coord_field():
for location in MyAppModels.Location.objects.all():
print(" old SRID : ", location.coord_field.srid)
location.update_coord_field()
location.save()
print(" new SRID : ", location.coord_field.srid)
update_all_coord_field()
但是当再次尝试执行我的脚本时(或者只是尝试使用我的新值属性),我只能观察到没有任何东西被保存到数据库中(它仍然 print
[的旧值=28=] 所有 Location
objects).
我的脚本是如何执行的:
python manage.py shell
exec(script.py)
如果我调用我的脚本两次,这里是以下追溯(只有一个 object 让想法可以理解):
exec(script.py)
old SRID : 4326
new SRID : 3857 # so apparently object has been updated...
exec(script.py)
old SRID: 4326 # ...but this line proves that the updated value has not been pushed to the database
new SRID: 3857
你知道为什么这不起作用吗?
第一次编辑:@JohnMoutafis 向我指出,已经有一个函数可以更改 Point
object 的 SRID
:transform
。
Location.objects.get(pk=pk).transform(3857) # define a new value of SRID
有用,但没有解决我的问题!请注意,我没有使用 transform
方法更新我的代码。
第二次编辑:我经历了很多痛苦才明白不是 save
方法不起作用!实际上,如果我尝试更新 MyAppModel
的 "casual" 数据字段,一切正常并按预期更新。真正的问题只是我的 coord_field
属性 无法 更新,我不知道为什么。
在我的脚本中,我一方面尝试了上面解释的内容,另一方面我也尝试了以下手动更新(而不是通过我的模型的自定义方法)coord_field
:
MyAppModels.Location.objects.filter(pk=pk).update(
geoCoord=Point(location.geoCoord.x, location.geoCoord.y, srid=3857),
valTest="meat"
)
因此,如果我再次执行我的脚本,我会看到 valTest
已正确更新(很好!),但 geoCoord
仍然是旧值! :-( 错误的 SRID 和所有内容。所以,我认为我在更新 geoDjango Point object
时确实遇到了问题,因此我会更新我的问题的标题!
基于此gis.stackexchange post,我假设您最初声明的每个点都没有显式 srid
,因此 GeoDajngo 假设您必须在 4326 上声明它。
您需要在数据库中明确声明每个点。
这是一个脚本,可以帮助您利用现有的积分来做到这一点。
for item in Location.objects.all():
item.coord_field = Point(item.coord_field.x, item.coord_field.y, srid=4326)
item.save()
您可以使用 transform
而不是您的自定义方法来更改您的点数 srid
:
Location.objects.all().transform(3857)
因评论而编辑:
由于@KrazyMax 在评论中提供了说明,他需要计算球面距离。我在这里做了一个 post:
已解决:我的结论是,一旦您指定了 Point
中的 SRID
,您以后就无法更改它。即使 transform
方法也不会改变 SRID
,而只会进行一些转换 就地 ,而不会改变 [=14] 的原始 SRID
=].实际上,我认为当我写:
coord_field = geoModels.PointField(blank=True, null=True)
默认的 4826 SRID
已经一次性设置到数据库的相应列(并且只有这个 SRID
可以用于该列)。所以,即使我写:
self.coord_field = Point(newLong, newLat, srid=newSRID)
我无法将另一个 SRID
关联到我的观点。将要计算一些微积分,但最终 Point
属性仍将受到初始 SRID
.
的影响
要明确:我不能 100% 确定这些结论(我没有找到任何合适的文档),但是删除 coord_field
列然后设置 coord_field
如下:
coord_field = geoModels.PointField(srid=3857, blank=True, null=True)
..成功了。如果有人为我提供了清晰的答案,我仍然会很高兴阅读它!
已解决:查看我自己的回答以获得解释。
我正在写一个 API 来帮助我在需要时维护我的数据库。
我的 API 的一个功能是更新所有相关 object 的特定 geoDjango Point
字段,这要归功于我的模型的专用方法(这是非常无用的重新编辑 EDIT 1,见下文)。
我一直面临的问题如下:在多个 object 上调用该方法时似乎没有任何内容保存到数据库中,即使对 save
方法的调用似乎在浏览 object 时工作。
参见 EDIT 2,我发现这个问题是 geoDjango Point
objects 特有的(其他所有内容都按预期更新)。
下面是我的模型:
models.py
class Location(geoModels.Model):
coord_field = geoModels.PointField(blank=True, null=True)
valTest = models.CharField(max_length=100, default="tagada") # only used to understand why coord_field can't be updated properly
def update_coord_field(self):
# some stuff is being done
self.coord_field = Point(
newLong,
newLat,
srid=3857 # I am trying to update that value
)
# nothing more
由于 Google 地图 API,正在生成 newLong
和 newLat
。
由于 Google 地图似乎与 SRID 3857
一起工作,而 GeoDjango 在创建新的 Point
时默认使用 SRID 4326
,我想强制 self.coord_field
的 SRID 为 SRID 3857
(我一直面临不一致的距离演算,所以我正在尝试使用 SRID 来解决这个问题)。
现在这是我的脚本:
script.py
from MyApp import models as MyAppModels
def update_all_coord_field():
for location in MyAppModels.Location.objects.all():
print(" old SRID : ", location.coord_field.srid)
location.update_coord_field()
location.save()
print(" new SRID : ", location.coord_field.srid)
update_all_coord_field()
但是当再次尝试执行我的脚本时(或者只是尝试使用我的新值属性),我只能观察到没有任何东西被保存到数据库中(它仍然 print
[的旧值=28=] 所有 Location
objects).
我的脚本是如何执行的:
python manage.py shell
exec(script.py)
如果我调用我的脚本两次,这里是以下追溯(只有一个 object 让想法可以理解):
exec(script.py)
old SRID : 4326
new SRID : 3857 # so apparently object has been updated...
exec(script.py)
old SRID: 4326 # ...but this line proves that the updated value has not been pushed to the database
new SRID: 3857
你知道为什么这不起作用吗?
第一次编辑:@JohnMoutafis 向我指出,已经有一个函数可以更改
Point
object 的 SRID
:transform
。
Location.objects.get(pk=pk).transform(3857) # define a new value of SRID
有用,但没有解决我的问题!请注意,我没有使用 transform
方法更新我的代码。
第二次编辑:我经历了很多痛苦才明白不是
save
方法不起作用!实际上,如果我尝试更新 MyAppModel
的 "casual" 数据字段,一切正常并按预期更新。真正的问题只是我的 coord_field
属性 无法 更新,我不知道为什么。
在我的脚本中,我一方面尝试了上面解释的内容,另一方面我也尝试了以下手动更新(而不是通过我的模型的自定义方法)coord_field
:
MyAppModels.Location.objects.filter(pk=pk).update(
geoCoord=Point(location.geoCoord.x, location.geoCoord.y, srid=3857),
valTest="meat"
)
因此,如果我再次执行我的脚本,我会看到 valTest
已正确更新(很好!),但 geoCoord
仍然是旧值! :-( 错误的 SRID 和所有内容。所以,我认为我在更新 geoDjango Point object
时确实遇到了问题,因此我会更新我的问题的标题!
基于此gis.stackexchange post,我假设您最初声明的每个点都没有显式 srid
,因此 GeoDajngo 假设您必须在 4326 上声明它。
您需要在数据库中明确声明每个点。
这是一个脚本,可以帮助您利用现有的积分来做到这一点。for item in Location.objects.all(): item.coord_field = Point(item.coord_field.x, item.coord_field.y, srid=4326) item.save()
您可以使用
transform
而不是您的自定义方法来更改您的点数srid
:Location.objects.all().transform(3857)
因评论而编辑:
由于@KrazyMax 在评论中提供了说明,他需要计算球面距离。我在这里做了一个 post:
已解决:我的结论是,一旦您指定了 Point
中的 SRID
,您以后就无法更改它。即使 transform
方法也不会改变 SRID
,而只会进行一些转换 就地 ,而不会改变 [=14] 的原始 SRID
=].实际上,我认为当我写:
coord_field = geoModels.PointField(blank=True, null=True)
默认的 4826 SRID
已经一次性设置到数据库的相应列(并且只有这个 SRID
可以用于该列)。所以,即使我写:
self.coord_field = Point(newLong, newLat, srid=newSRID)
我无法将另一个 SRID
关联到我的观点。将要计算一些微积分,但最终 Point
属性仍将受到初始 SRID
.
要明确:我不能 100% 确定这些结论(我没有找到任何合适的文档),但是删除 coord_field
列然后设置 coord_field
如下:
coord_field = geoModels.PointField(srid=3857, blank=True, null=True)
..成功了。如果有人为我提供了清晰的答案,我仍然会很高兴阅读它!