1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Refs #33783 -- Added IsEmpty GIS database function and __isempty lookup on SpatiaLite.

This commit is contained in:
David Smith 2024-09-29 16:53:46 +01:00
parent 43287cbb87
commit 1e67d1a061
7 changed files with 59 additions and 7 deletions

View File

@ -82,7 +82,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations):
@cached_property
def unsupported_functions(self):
unsupported = {"GeometryDistance", "IsEmpty", "MemSize"}
unsupported = {"GeometryDistance", "MemSize"}
if not self.geom_lib_version():
unsupported |= {"Azimuth", "GeoHash", "MakeValid"}
if self.spatial_version < (5, 1):

View File

@ -359,7 +359,7 @@ Lookup Type PostGIS Oracle MariaDB MySQL [#]_ S
:lookup:`equals` X X X X X C
:lookup:`exact <same_as>` 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 (≥ 11.7) X X
:lookup:`overlaps` X X X X X B
:lookup:`relate` X X X X C
@ -408,7 +408,7 @@ Function PostGIS Oracle MariaDB MySQL
:class:`FromWKT` X X X X X
:class:`GeoHash` X X (≥ 11.7) X X (LWGEOM/RTTOPO)
:class:`Intersection` X X X X X
:class:`IsEmpty` X
:class:`IsEmpty` X X
:class:`IsValid` X X X (≥ 11.7) X X
:class:`Length` X X X X X
:class:`LineLocatePoint` X X

View File

@ -438,11 +438,16 @@ intersection between them.
.. 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
geometry. Returns ``True`` if its value is empty and ``False`` otherwise.
.. versionchanged:: 5.2
Support for SpatiaLite was added.
``IsValid``
===========

View File

@ -362,7 +362,8 @@ SpatiaLite ``Intersects(poly, geom)``
``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.
@ -372,6 +373,10 @@ Example::
.. fieldlookup:: isvalid
.. versionchanged:: 5.2
Support for SpatiaLite was added.
``isvalid``
-----------

View File

@ -108,6 +108,10 @@ Minor features
:class:`~django.contrib.gis.db.models.functions.IsValid` database functions
are now supported on MariaDB 11.7+.
* The :lookup:`isempty` lookup and
:class:`~django.contrib.gis.db.models.functions.IsEmpty` expression are now
supported on SpatiaLite.
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -28,6 +28,13 @@ class City(NamedModel):
app_label = "geoapp"
class Town(NamedModel):
point = models.PointField(null=True)
class Meta:
app_label = "geoapp"
# This is an inherited model from City
class PennsylvaniaCity(City):
county = models.CharField(max_length=30)

View File

@ -11,7 +11,15 @@ from django.db.models import IntegerField, Sum, Value
from django.test import TestCase, skipUnlessDBFeature
from ..utils import FuncTestMixin
from .models import City, Country, CountryWebMercator, ManyPointModel, State, Track
from .models import (
City,
Country,
CountryWebMercator,
ManyPointModel,
State,
Town,
Track,
)
class GISFunctionsTests(FuncTestMixin, TestCase):
@ -413,7 +421,7 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
self.assertIs(c.inter.empty, True)
@skipUnlessDBFeature("supports_empty_geometries", "has_IsEmpty_function")
def test_isempty(self):
def test_isempty_empty_geometry(self):
empty = City.objects.create(name="Nowhere", point=Point(srid=4326))
City.objects.create(name="Somewhere", point=Point(6.825, 47.1, srid=4326))
self.assertSequenceEqual(
@ -424,6 +432,29 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
)
self.assertSequenceEqual(City.objects.filter(point__isempty=True), [empty])
@skipUnlessDBFeature("has_IsEmpty_function")
def test_isempty_null_geometry(self):
null_geometry = Town.objects.create(name="Nowhere", point=None)
Town.objects.create(name="Somewhere", point=Point(6.825, 47.1, srid=4326))
if connection.ops.spatialite:
self.assertSequenceEqual(
Town.objects.annotate(isempty=functions.IsEmpty("point")).filter(
isempty=True
),
[null_geometry],
)
self.assertSequenceEqual(
Town.objects.filter(point__isempty=True), [null_geometry]
)
else:
self.assertSequenceEqual(
Town.objects.annotate(isempty=functions.IsEmpty("point")).filter(
isempty=True
),
[],
)
self.assertSequenceEqual(Town.objects.filter(point__isempty=True), [])
@skipUnlessDBFeature("has_IsValid_function")
def test_isvalid(self):
valid_geom = fromstr("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))")