Search code examples
django-admingeospatialgeodjango

Latitude longitude confusion using GeoDjango and OSMGeoAdmin


I'm trying to store a polygon using OSMGeoAdmin map widget and I've declared my admin class like this:

class ProjectAdmin(OSMGeoAdmin):
    default_lon = 4600000
    default_lat = 180000
    default_zoom = 4

And this is my geometry models base class:

class AbstractGeometryModel(models.Model):
    class Meta:
        abstract = True

    geometry = models.MultiPolygonField()

    @property
    def boundary(self):
        boundary = self.geometry.boundary[0]
        return [[x[1], x[0]] for x in boundary]

    @property
    def bbox(self):
        box = self.geometry.extent
        return [[box[1], box[0]], [box[3], box[2]]]

    @property
    def centroid(self):
        return [self.geometry.centroid[1], self.geometry.centroid[0]]

As mentioned in Django docs, the default SRID should be 4326, and as I checked personally, when you get the extent of a geometry it's in [lat, lon, lat, lon] format, and I needed them to be lon, lat so I wrote those property methods.

The problem is, whenever I deploy my service in a new production env or bring it up from scratch in a local development environment, I see that the lat, lons are stored in reverse format.

to check this problem, I decided to compare the production database with my local development db, and here are the results:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> production_data = GEOSGeometry('0106...(Geometry copied from production db)...1532')
>>> production_data.extent
(17.2922570380823, 44.879874515170165, 18.00644604063442, 46.02245264001086)
>>> production_data.srid
4326
>>> development_data = GEOSGeometry('0106...(Geometry copied from development db)...1532')
>>> development_data.extent
(44.75627832378126, 17.887728306166515, 46.09661035484472, 18.10414680358874)
>>> development_data.srid
4326

As you can see, the SRIDs are the same but data is stored as lat, lon in production db, and also as lon, lat in local db!

I tried to debug to find out what's going on, but I didn't succeed. I'll appreciate it if someone can help me with this problem. Thanks.

UPDATE I also run below code both in server and local python console:

local:

Python 3.8.3rc1 (default, May 10 2020, 12:11:09) 
[GCC 7.4.0] on linux
Django 2.2.4
>>> from django.contrib.gis.geos import GEOSGeometry
>>> a = GEOSGeometry('SRID=3857;MULTIPOLYGON(((..lots of geo numbers...)))')
>>> a.transofrm(4326)
>>> a.extent
(34.109070627613065, 46.87535791416505, 36.24604033684087, 53.423209475753794)

server:

root@fdfd7ccf489b:/code# python manage.py shell
Python 3.7.6 (default, Feb 26 2020, 15:34:58) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from django.contrib.gis.geos import GEOSGeometry                                                                                                                                                                                      

In [2]: a = GEOSGeometry('SRID=3857;MULTIPOLYGON(((..lots of geo numbers...)))')                       

In [3]: a.extent                                                                                                                                                                                                                              
Out[3]: (5218140.9737573, 4043456.9660937, 5947044.4753833, 4334529.1697632)

In [4]: a.transform(4326)                                                                                                                                                                                                                     

In [5]: a.extent                                                                                                                                                                                                                              
Out[5]: (46.875357914165036, 34.10907062761305, 53.42320947575378, 36.246040336840856)

so it seems that problem is something related to the GeoDjango version or config...


Solution

  • It seems that the root source of the problem is different versions of GDAL installed on production (GDAL 2.4.0) and local (GDAL 3.0.1) environment.

    https://code.djangoproject.com/ticket/31695#no1