diff --git a/django/contrib/gis/db/backend/oracle/field.py b/django/contrib/gis/db/backend/oracle/field.py index 9d971a3b22..695b33369a 100644 --- a/django/contrib/gis/db/backend/oracle/field.py +++ b/django/contrib/gis/db/backend/oracle/field.py @@ -4,7 +4,7 @@ from django.db import connection from django.db.backends.util import truncate_name from django.db.models.fields import Field # Django base Field class from django.contrib.gis.geos import GEOSGeometry -from django.contrib.gis.db.backend.util import GeoFieldSQL +from django.contrib.gis.db.backend.util import get_srid, GeoFieldSQL from django.contrib.gis.db.backend.oracle.adaptor import OracleSpatialAdaptor from django.contrib.gis.db.backend.oracle.query import ORACLE_SPATIAL_TERMS, TRANSFORM @@ -118,8 +118,7 @@ class OracleSpatialField(Field): # Getting the SRID of the geometry, or defaulting to that of the field if # it is None. - if value.srid is None: srid = self._srid - else: srid = value.srid + srid = get_srid(self, value) # The adaptor will be used by psycopg2 for quoting the WKT. adapt = OracleSpatialAdaptor(value) diff --git a/django/contrib/gis/db/backend/postgis/field.py b/django/contrib/gis/db/backend/postgis/field.py index 6fc743ee1f..442795efd4 100644 --- a/django/contrib/gis/db/backend/postgis/field.py +++ b/django/contrib/gis/db/backend/postgis/field.py @@ -2,7 +2,7 @@ from types import StringType, UnicodeType from django.db import connection from django.db.models.fields import Field # Django base Field class from django.contrib.gis.geos import GEOSGeometry, GEOSException -from django.contrib.gis.db.backend.util import GeoFieldSQL +from django.contrib.gis.db.backend.util import get_srid, GeoFieldSQL from django.contrib.gis.db.backend.postgis.adaptor import PostGISAdaptor from django.contrib.gis.db.backend.postgis.query import POSTGIS_TERMS, TRANSFORM from psycopg2 import Binary @@ -109,8 +109,7 @@ class PostGISField(Field): # Getting the SRID of the geometry, or defaulting to that of the field if # it is None. - if value.srid is None: srid = self._srid - else: srid = value.srid + srid = get_srid(self, value) # The adaptor will be used by psycopg2 for quoting the WKB. adapt = PostGISAdaptor(value, srid) diff --git a/django/contrib/gis/db/backend/util.py b/django/contrib/gis/db/backend/util.py index d49376033b..34c5c9a280 100644 --- a/django/contrib/gis/db/backend/util.py +++ b/django/contrib/gis/db/backend/util.py @@ -6,3 +6,13 @@ class GeoFieldSQL(object): def __init__(self, where=[], params=[]): self.where = where self.params = params + +def get_srid(field, geom): + """ + Gets the SRID depending on the value of the SRID setting of the field + and that of the given geometry. + """ + if geom.srid is None or (geom.srid == -1 and field._srid != -1): + return field._srid + else: + return geom.srid diff --git a/django/contrib/gis/geos/base.py b/django/contrib/gis/geos/base.py index 53cfb7ebb5..ef8a47edad 100644 --- a/django/contrib/gis/geos/base.py +++ b/django/contrib/gis/geos/base.py @@ -48,14 +48,12 @@ class GEOSGeometry(object): The `srid` keyword is used to specify the Source Reference Identifier (SRID) number for this Geometry. If not set, the SRID will be None. """ - from_hex = False if isinstance(geo_input, UnicodeType): # Encoding to ASCII, WKT or HEXEWKB doesn't need any more. geo_input = geo_input.encode('ascii') if isinstance(geo_input, StringType): if hex_regex.match(geo_input): # If the regex matches, the geometry is in HEX form. - from_hex = True sz = c_size_t(len(geo_input)) buf = create_string_buffer(geo_input) g = lgeos.GEOSGeomFromHEX_buf(buf, sz) @@ -86,10 +84,6 @@ class GEOSGeometry(object): # Setting the SRID, if given. if srid and isinstance(srid, int): self.srid = srid - # Exported HEX from other GEOS geometries will have -1 SRID -- - # set here to 0, when the SRID is not explicitly given. - if not srid and from_hex: self.srid = 0 - # Setting the class type (e.g., 'Point', 'Polygon', etc.) self.__class__ = GEOS_CLASSES[self.geom_type] @@ -422,6 +416,8 @@ class GEOSGeometry(object): included in this representation, because the GEOS C library uses -1 by default, even if the SRID is set. """ + # A possible faster, all-python, implementation: + # str(self.wkb).encode('hex') sz = c_size_t() h = lgeos.GEOSGeomToHEX_buf(self._ptr(), byref(sz)) return string_at(h, sz.value) diff --git a/django/contrib/gis/tests/geoapp/tests.py b/django/contrib/gis/tests/geoapp/tests.py index 8f65dd84f0..1239b53cb3 100644 --- a/django/contrib/gis/tests/geoapp/tests.py +++ b/django/contrib/gis/tests/geoapp/tests.py @@ -138,10 +138,12 @@ class GeoModelTest(unittest.TestCase): # the pre-transformed points. Oracle does not have the 3084 SRID. if not oracle: h = City.objects.transform('point', srid=htown.srid).get(name='Houston') + self.assertEqual(3084, h.point.srid) self.assertAlmostEqual(htown.x, h.point.x, 8) self.assertAlmostEqual(htown.y, h.point.y, 8) p = City.objects.transform('point', srid=ptown.srid).get(name='Pueblo') + self.assertEqual(2774, p.point.srid) self.assertAlmostEqual(ptown.x, p.point.x, 7) self.assertAlmostEqual(ptown.y, p.point.y, 7) diff --git a/django/contrib/gis/tests/test_gdal.py b/django/contrib/gis/tests/test_gdal.py index c7c33fb6e1..030ac505fe 100644 --- a/django/contrib/gis/tests/test_gdal.py +++ b/django/contrib/gis/tests/test_gdal.py @@ -1,3 +1,7 @@ +""" +Module for executing all of the GDAL tests. None +of these tests require the use of the database. +""" from unittest import TestSuite, TextTestRunner # Importing the GDAL test modules. @@ -20,5 +24,5 @@ def suite(): return s def run(verbosity=1): - "Runs the tests that do not require geographic (GEOS, GDAL, etc.) models." + "Runs the GDAL tests." TextTestRunner(verbosity=verbosity).run(suite()) diff --git a/django/contrib/gis/tests/test_geos.py b/django/contrib/gis/tests/test_geos.py index be7de1f981..d78c45edd5 100644 --- a/django/contrib/gis/tests/test_geos.py +++ b/django/contrib/gis/tests/test_geos.py @@ -607,6 +607,21 @@ class GEOSTest(unittest.TestCase): self.assertEqual(32021, gc.srid) for i in range(len(gc)): self.assertEqual(32021, gc[i].srid) + # GEOS may get the SRID from HEXEWKB + # 'POINT(5 23)' at SRID=4326 in hex form -- obtained from PostGIS + # using `SELECT GeomFromText('POINT (5 23)', 4326);`. + hex = '0101000020E610000000000000000014400000000000003740' + p1 = fromstr(hex) + self.assertEqual(4326, p1.srid) + + # However, when HEX is exported, the SRID information is lost + # and set to -1. Essentially, the 'E' of the EWKB is not + # encoded in HEX by the GEOS C library for some reason. + p2 = fromstr(p1.hex) + self.assertEqual(-1, p2.srid) + p3 = fromstr(p1.hex, srid=-1) # -1 is intended. + self.assertEqual(-1, p3.srid) + def test16_mutable_geometries(self): "Testing the mutability of Polygons and Geometry Collections." ### Testing the mutability of Polygons ###