diff --git a/django/contrib/gis/db/models/functions.py b/django/contrib/gis/db/models/functions.py index acbaa5ffc0..10272b7d68 100644 --- a/django/contrib/gis/db/models/functions.py +++ b/django/contrib/gis/db/models/functions.py @@ -367,15 +367,28 @@ class ForcePolygonCW(GeomOutputGeoFunc): class FromWKB(GeoFunc): - output_field = GeometryField(srid=0) - arity = 1 + arity = 2 geom_param_pos = () + def __init__(self, expression, srid=0, **extra): + expressions = [ + expression, + self._handle_param(srid, "srid", int), + ] + if "output_field" not in extra: + extra["output_field"] = GeometryField(srid=srid) + super().__init__(*expressions, **extra) -class FromWKT(GeoFunc): - output_field = GeometryField(srid=0) - arity = 1 - geom_param_pos = () + def as_oracle(self, compiler, connection, **extra_context): + # Oracle doesn't support the srid parameter. + source_expressions = self.get_source_expressions() + clone = self.copy() + clone.set_source_expressions(source_expressions[:1]) + return super(FromWKB, clone).as_sql(compiler, connection, **extra_context) + + +class FromWKT(FromWKB): + pass class GeoHash(GeoFunc): diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt index f55d314b3f..3fff7eeb50 100644 --- a/docs/ref/contrib/gis/functions.txt +++ b/docs/ref/contrib/gis/functions.txt @@ -359,24 +359,36 @@ are returned unchanged. ``FromWKB`` =========== -.. class:: FromWKB(expression, **extra) +.. class:: FromWKB(expression, srid=0, **extra) *Availability*: MariaDB, `MySQL `__, Oracle, `PostGIS `__, SpatiaLite -Creates geometry from `Well-known binary (WKB)`_ representation. +Creates geometry from `Well-known binary (WKB)`_ representation. The optional +``srid`` argument allows to specify the SRID of the resulting geometry. +``srid`` is ignored on Oracle. + +.. versionchanged:: 5.1 + + The ``srid`` argument was added. ``FromWKT`` =========== -.. class:: FromWKT(expression, **extra) +.. class:: FromWKT(expression, srid=0, **extra) *Availability*: MariaDB, `MySQL `__, Oracle, `PostGIS `__, SpatiaLite -Creates geometry from `Well-known text (WKT)`_ representation. +Creates geometry from `Well-known text (WKT)`_ representation. The optional +``srid`` argument allows to specify the SRID of the resulting geometry. +``srid`` is ignored on Oracle. + +.. versionchanged:: 5.1 + + The ``srid`` argument was added. ``GeoHash`` =========== diff --git a/docs/releases/5.1.txt b/docs/releases/5.1.txt index 5fe2be96c8..2dbacf08f7 100644 --- a/docs/releases/5.1.txt +++ b/docs/releases/5.1.txt @@ -101,6 +101,11 @@ Minor features * :attr:`.OGRGeometry.centroid` is now available on all supported geometry types. +* :class:`FromWKB() ` and + :class:`FromWKT() ` functions + now support the optional ``srid`` argument (except for Oracle where it is + ignored). + :mod:`django.contrib.messages` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py index 0be690347e..80b08f8d39 100644 --- a/tests/gis_tests/geoapp/test_functions.py +++ b/tests/gis_tests/geoapp/test_functions.py @@ -348,20 +348,24 @@ class GISFunctionsTests(FuncTestMixin, TestCase): @skipUnlessDBFeature("has_FromWKB_function") def test_fromwkb(self): g = Point(56.811078, 60.608647) - g2 = City.objects.values_list( + pt1, pt2 = City.objects.values_list( functions.FromWKB(Value(g.wkb.tobytes())), - flat=True, + functions.FromWKB(Value(g.wkb.tobytes()), srid=4326), )[0] - self.assertIs(g.equals_exact(g2, 0.00001), True) + self.assertIs(g.equals_exact(pt1, 0.00001), True) + self.assertIsNone(pt1.srid) + self.assertEqual(pt2.srid, 4326) @skipUnlessDBFeature("has_FromWKT_function") def test_fromwkt(self): g = Point(56.811078, 60.608647) - g2 = City.objects.values_list( + pt1, pt2 = City.objects.values_list( functions.FromWKT(Value(g.wkt)), - flat=True, + functions.FromWKT(Value(g.wkt), srid=4326), )[0] - self.assertIs(g.equals_exact(g2, 0.00001), True) + self.assertIs(g.equals_exact(pt1, 0.00001), True) + self.assertIsNone(pt1.srid) + self.assertEqual(pt2.srid, 4326) @skipUnlessDBFeature("has_GeoHash_function") def test_geohash(self):