Reputation: 959
One function of my API is for updating a specific geoDjango Point
field of all the concerned objects, thanks to a dedicated method of my model (which is pretty useless rergading to EDIT 1, see below).
The issue I have been facing with is the following: nothing seems to be saved to the database when calling that method on several objects, even if a call to save
method seems to work while browsing the objects.
See EDIT 2, I figured out this issue was specific to geoDjango Point
objects (everything else is being updated as expected).
Here below is my model:
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
newLong
and newLat
are being generated thanks to Google Maps API.
As Google Maps seems to be working with SRID 3857
while GeoDjango uses SRID 4326
by default when creating a new Point
, I want to force SRID of self.coord_field
to SRID 3857
(I have been facing incoherent distance calculus, so I am trying to play with SRID to solve that).
Now here is my script :
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()
But when trying to execute my script again (or simply just trying to use my new valued attribute), I can only observe that nothing was saved to the db (it still print
the old value of location.coord_field.srid
for all Location
objects).
How my script is being executed:
python manage.py shell
exec(script.py)
If I call twice my script, here is the following traceback (only one object to make thinks understandable):
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
Do you have any idea why is this not working?
SRID
of Point
objects: transform
.
Location.objects.get(pk=pk).transform(3857) # define a new value of SRID
It is usefull, yet it does not solve my issue! Please notice I did not update my code here with that transform
method.
save
method which is not working! Actually, if I try to update "casual" data field of MyAppModel
, everything works fine and is updated as expected. The real issue is only about my coord_field
attribute which can't be updated, and I can't figure out why.
In my script I tried on the one hand what I explained above, and on the other hand I also tried the following to update manually (and not through a custom method of my model) coord_field
:
MyAppModels.Location.objects.filter(pk=pk).update(
geoCoord=Point(location.geoCoord.x, location.geoCoord.y, srid=3857),
valTest="meat"
)
As a result, if I execute again my script, I see that valTest
has been properly updated (nice!), but geoCoord
still is the old value! :-( With the wrong SRID and everything. So, I think I really have a trouble updating geoDjango Point object
in particular, and will update the title of my question as a consequence of that!
Upvotes: 1
Views: 497
Reputation: 959
SOLVED: my conlusion is that once you specified SRID
of one Point
, you can not change it later. Even the transform
method won't change SRID
, but will only make some conversion in place, without altering original SRID
of your Point
. Actually, I think that when I write:
coord_field = geoModels.PointField(blank=True, null=True)
the default 4826 SRID
is already set once for all to the appropriate column of the database (and only this SRID
can then be used for this column). So, even when I write:
self.coord_field = Point(newLong, newLat, srid=newSRID)
I won't be able to associate another SRID
to my Point. Some calculus is going to be computed, but at the end the Point
attribute will still be affected of the initial SRID
.
To be clear: I am not sure 100% about those conclusions (I did not find any appropriate doc), but deleting coord_field
column then setting coord_field
as follows:
coord_field = geoModels.PointField(srid=3857, blank=True, null=True)
..did the trick. If anyone has got some clean answer for me, I would still appreciate to read it!
Upvotes: 1
Reputation: 23134
Based on this gis.stackexchange post, I will assume that you are declaring each point initially without an explicit srid
, therefore GeoDajngo assumes that you must have declared it on 4326.
You need to declare every point in your database explicitly.
Here is a script to help you do that with your existing points.
for item in Location.objects.all():
item.coord_field = Point(item.coord_field.x, item.coord_field.y, srid=4326)
item.save()
You can use transform
instead of your custom method to change the srid
of your Points:
Location.objects.all().transform(3857)
EDIT due to comment:
Since clarification provided by @KrazyMax on the comments, he needs to calculate the spherical distance. I have made a post about that here: How to calculate 3D distance (including altitude) between two points in GeoDjango
Upvotes: 1