mirror of
https://github.com/django/django.git
synced 2025-09-25 07:59:11 +00:00
Refs #33783 -- Added IsEmpty GIS database function and __isempty lookup on SpatiaLite.
This commit is contained in:
parent
6fe96639ba
commit
e20e189045
@ -73,6 +73,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
|||||||
"ForcePolygonCW": "ST_ForceLHR",
|
"ForcePolygonCW": "ST_ForceLHR",
|
||||||
"FromWKB": "ST_GeomFromWKB",
|
"FromWKB": "ST_GeomFromWKB",
|
||||||
"FromWKT": "ST_GeomFromText",
|
"FromWKT": "ST_GeomFromText",
|
||||||
|
"IsEmpty": "ST_IsEmpty",
|
||||||
"Length": "ST_Length",
|
"Length": "ST_Length",
|
||||||
"LineLocatePoint": "ST_Line_Locate_Point",
|
"LineLocatePoint": "ST_Line_Locate_Point",
|
||||||
"NumPoints": "ST_NPoints",
|
"NumPoints": "ST_NPoints",
|
||||||
@ -84,7 +85,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def unsupported_functions(self):
|
def unsupported_functions(self):
|
||||||
unsupported = {"GeometryDistance", "IsEmpty", "MemSize", "Rotate"}
|
unsupported = {"GeometryDistance", "MemSize", "Rotate"}
|
||||||
if not self.geom_lib_version():
|
if not self.geom_lib_version():
|
||||||
unsupported |= {"Azimuth", "GeoHash", "MakeValid"}
|
unsupported |= {"Azimuth", "GeoHash", "MakeValid"}
|
||||||
if self.spatial_version < (5, 1):
|
if self.spatial_version < (5, 1):
|
||||||
|
@ -451,6 +451,10 @@ class IsEmpty(GeoFuncMixin, Transform):
|
|||||||
lookup_name = "isempty"
|
lookup_name = "isempty"
|
||||||
output_field = BooleanField()
|
output_field = BooleanField()
|
||||||
|
|
||||||
|
def as_sqlite(self, compiler, connection, **extra_context):
|
||||||
|
sql, params = super().as_sql(compiler, connection, **extra_context)
|
||||||
|
return "NULLIF(%s, -1)" % sql, params
|
||||||
|
|
||||||
|
|
||||||
@BaseSpatialField.register_lookup
|
@BaseSpatialField.register_lookup
|
||||||
class IsValid(OracleToleranceMixin, GeoFuncMixin, Transform):
|
class IsValid(OracleToleranceMixin, GeoFuncMixin, Transform):
|
||||||
|
@ -363,7 +363,7 @@ Lookup Type PostGIS Oracle MariaDB MySQL [#]_
|
|||||||
:lookup:`exact <same_as>` X X X X X B
|
:lookup:`exact <same_as>` X X X X X B
|
||||||
:lookup:`geom_type` X X (≥ 23c) X X X
|
:lookup:`geom_type` X X (≥ 23c) X X X
|
||||||
:lookup:`intersects` X X X X X B
|
:lookup:`intersects` X X X X X B
|
||||||
:lookup:`isempty` X
|
:lookup:`isempty` X X
|
||||||
:lookup:`isvalid` X X X (≥ 12.0.1) X X
|
:lookup:`isvalid` X X X (≥ 12.0.1) X X
|
||||||
:lookup:`overlaps` X X X X X B
|
:lookup:`overlaps` X X X X X B
|
||||||
:lookup:`relate` X X X X C
|
:lookup:`relate` X X X X C
|
||||||
@ -414,7 +414,7 @@ Function PostGIS Oracle MariaDB MySQL
|
|||||||
:class:`GeometryDistance` X
|
:class:`GeometryDistance` X
|
||||||
:class:`GeometryType` X X (≥ 23c) X X X
|
:class:`GeometryType` X X (≥ 23c) X X X
|
||||||
:class:`Intersection` X X X X X
|
:class:`Intersection` X X X X X
|
||||||
:class:`IsEmpty` X
|
:class:`IsEmpty` X X
|
||||||
:class:`IsValid` X X X (≥ 12.0.1) X X
|
:class:`IsValid` X X X (≥ 12.0.1) X X
|
||||||
:class:`Length` X X X X X
|
:class:`Length` X X X X X
|
||||||
:class:`LineLocatePoint` X X
|
:class:`LineLocatePoint` X X
|
||||||
|
@ -621,11 +621,16 @@ Miscellaneous
|
|||||||
|
|
||||||
.. class:: IsEmpty(expr)
|
.. class:: IsEmpty(expr)
|
||||||
|
|
||||||
*Availability*: `PostGIS <https://postgis.net/docs/ST_IsEmpty.html>`__
|
*Availability*: `PostGIS <https://postgis.net/docs/ST_IsEmpty.html>`__,
|
||||||
|
SpatiaLite
|
||||||
|
|
||||||
Accepts a geographic field or expression and tests if the value is an empty
|
Accepts a geographic field or expression and tests if the value is an empty
|
||||||
geometry. Returns ``True`` if its value is empty and ``False`` otherwise.
|
geometry. Returns ``True`` if its value is empty and ``False`` otherwise.
|
||||||
|
|
||||||
|
.. versionchanged:: 6.1
|
||||||
|
|
||||||
|
SpatiaLite support was added.
|
||||||
|
|
||||||
``IsValid``
|
``IsValid``
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -361,7 +361,8 @@ SpatiaLite ``Intersects(poly, geom)``
|
|||||||
``isempty``
|
``isempty``
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
*Availability*: `PostGIS <https://postgis.net/docs/ST_IsEmpty.html>`__
|
*Availability*: `PostGIS <https://postgis.net/docs/ST_IsEmpty.html>`__,
|
||||||
|
SpatiaLite
|
||||||
|
|
||||||
Tests if the geometry is empty.
|
Tests if the geometry is empty.
|
||||||
|
|
||||||
@ -369,6 +370,10 @@ Example::
|
|||||||
|
|
||||||
Zipcode.objects.filter(poly__isempty=True)
|
Zipcode.objects.filter(poly__isempty=True)
|
||||||
|
|
||||||
|
.. versionchanged:: 6.1
|
||||||
|
|
||||||
|
SpatiaLite support was added.
|
||||||
|
|
||||||
.. fieldlookup:: isvalid
|
.. fieldlookup:: isvalid
|
||||||
|
|
||||||
``isvalid``
|
``isvalid``
|
||||||
|
@ -53,7 +53,9 @@ Minor features
|
|||||||
:mod:`django.contrib.gis`
|
:mod:`django.contrib.gis`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The :lookup:`isempty` lookup and
|
||||||
|
:class:`IsEmpty() <django.contrib.gis.db.models.functions.IsEmpty>`
|
||||||
|
database function are now supported on SpatiaLite.
|
||||||
|
|
||||||
:mod:`django.contrib.messages`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -431,7 +431,7 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
|
|||||||
self.assertIs(c.inter.empty, True)
|
self.assertIs(c.inter.empty, True)
|
||||||
|
|
||||||
@skipUnlessDBFeature("supports_empty_geometries", "has_IsEmpty_function")
|
@skipUnlessDBFeature("supports_empty_geometries", "has_IsEmpty_function")
|
||||||
def test_isempty(self):
|
def test_isempty_geometry_empty(self):
|
||||||
empty = City.objects.create(name="Nowhere", point=Point(srid=4326))
|
empty = City.objects.create(name="Nowhere", point=Point(srid=4326))
|
||||||
City.objects.create(name="Somewhere", point=Point(6.825, 47.1, srid=4326))
|
City.objects.create(name="Somewhere", point=Point(6.825, 47.1, srid=4326))
|
||||||
self.assertSequenceEqual(
|
self.assertSequenceEqual(
|
||||||
@ -442,6 +442,18 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
|
|||||||
)
|
)
|
||||||
self.assertSequenceEqual(City.objects.filter(point__isempty=True), [empty])
|
self.assertSequenceEqual(City.objects.filter(point__isempty=True), [empty])
|
||||||
|
|
||||||
|
@skipUnlessDBFeature("has_IsEmpty_function")
|
||||||
|
def test_isempty_geometry_null(self):
|
||||||
|
nowhere = State.objects.create(name="Nowhere", poly=None)
|
||||||
|
qs = State.objects.annotate(isempty=functions.IsEmpty("poly"))
|
||||||
|
self.assertSequenceEqual(qs.filter(isempty=None), [nowhere])
|
||||||
|
self.assertSequenceEqual(
|
||||||
|
qs.filter(isempty=False).order_by("name").values_list("name", flat=True),
|
||||||
|
["Colorado", "Kansas"],
|
||||||
|
)
|
||||||
|
self.assertSequenceEqual(qs.filter(isempty=True), [])
|
||||||
|
self.assertSequenceEqual(State.objects.filter(poly__isempty=True), [])
|
||||||
|
|
||||||
@skipUnlessDBFeature("has_IsValid_function")
|
@skipUnlessDBFeature("has_IsValid_function")
|
||||||
def test_isvalid(self):
|
def test_isvalid(self):
|
||||||
valid_geom = fromstr("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))")
|
valid_geom = fromstr("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user