mirror of
https://github.com/django/django.git
synced 2024-11-21 19:09:18 +01:00
added support for geom_type lookup
This commit is contained in:
parent
35ab2e0182
commit
94d86713a4
@ -8,6 +8,7 @@ from django.db import NotSupportedError
|
|||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
BinaryField,
|
BinaryField,
|
||||||
BooleanField,
|
BooleanField,
|
||||||
|
CharField,
|
||||||
FloatField,
|
FloatField,
|
||||||
Func,
|
Func,
|
||||||
IntegerField,
|
IntegerField,
|
||||||
@ -421,6 +422,37 @@ class Intersection(OracleToleranceMixin, GeomOutputGeoFunc):
|
|||||||
geom_param_pos = (0, 1)
|
geom_param_pos = (0, 1)
|
||||||
|
|
||||||
|
|
||||||
|
@BaseSpatialField.register_lookup
|
||||||
|
class GeometryType(GeoFuncMixin, Transform):
|
||||||
|
function = "GeometryType"
|
||||||
|
output_field = CharField()
|
||||||
|
lookup_name = "geom_type"
|
||||||
|
|
||||||
|
def as_mysql(self, compiler, connection, **extra_context):
|
||||||
|
lhs, params = compiler.compile(self.lhs)
|
||||||
|
sql = f"ST_GeometryType({lhs})"
|
||||||
|
return sql, params
|
||||||
|
|
||||||
|
def as_oracle(self, compiler, connection, **extra_context):
|
||||||
|
lhs, params = compiler.compile(self.lhs)
|
||||||
|
|
||||||
|
sql = f"""
|
||||||
|
(SELECT DECODE(
|
||||||
|
SDO_GEOMETRY.GET_GTYPE({lhs}),
|
||||||
|
1, 'POINT',
|
||||||
|
2, 'LINESTRING',
|
||||||
|
3, 'POLYGON',
|
||||||
|
4, 'COLLECTION',
|
||||||
|
5, 'MULTIPOINT',
|
||||||
|
6, 'MULTILINESTRING',
|
||||||
|
7, 'MULTIPOLYGON',
|
||||||
|
8, 'SOLID',
|
||||||
|
'UNKNOWN')
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
return sql, params
|
||||||
|
|
||||||
|
|
||||||
@BaseSpatialField.register_lookup
|
@BaseSpatialField.register_lookup
|
||||||
class IsEmpty(GeoFuncMixin, Transform):
|
class IsEmpty(GeoFuncMixin, Transform):
|
||||||
lookup_name = "isempty"
|
lookup_name = "isempty"
|
||||||
|
@ -692,6 +692,34 @@ PostGIS equivalent:
|
|||||||
|
|
||||||
.. _distance-lookups:
|
.. _distance-lookups:
|
||||||
|
|
||||||
|
.. fieldlookup:: geom_type
|
||||||
|
|
||||||
|
``geom_type``
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
*Availability*: `PostGIS <https://postgis.net/docs/GeometryType.html>`__,
|
||||||
|
Oracle, MariaDB, MySQL, SpatiaLite
|
||||||
|
|
||||||
|
Returns the geometry type of the geometry field.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
Shape.objects.filter(poly__geom_type=GeometryType("circle"))
|
||||||
|
|
||||||
|
========== ==========================
|
||||||
|
Backend SQL Equivalent
|
||||||
|
========== ==========================
|
||||||
|
PostGIS ``GeometryType(geom)``
|
||||||
|
MariaDB ``ST_GeometryType(geom)``
|
||||||
|
MySQL ``ST_GeometryType(geom)``
|
||||||
|
Oracle ``SDO_GEOMETRY.GET_GTYPE(geom)``
|
||||||
|
SpatiaLite ``GeometryType(geom)``
|
||||||
|
========== ==========================
|
||||||
|
|
||||||
|
Note that the ``GeometryType`` functions returns the string type but
|
||||||
|
``SDO_GEOMETRY.GET_GTYPE`` function returns the type encoded as a number.
|
||||||
|
Thus, those numbers are mapped to the string counterparts as per `Oracle's documentation <https://docs.oracle.com/database/121/SPATL/sdo_geometry-object-type.htm#GUID-4D84CE67-67E4-4A84-8255-C586E765A94B__G1013735>`_
|
||||||
|
|
||||||
Distance Lookups
|
Distance Lookups
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ Minor features
|
|||||||
:attr:`.OGRGeometry.has_curve` property, and the
|
:attr:`.OGRGeometry.has_curve` property, and the
|
||||||
:meth:`.OGRGeometry.get_linear_geometry` and
|
:meth:`.OGRGeometry.get_linear_geometry` and
|
||||||
:meth:`.OGRGeometry.get_curve_geometry` methods.
|
:meth:`.OGRGeometry.get_curve_geometry` methods.
|
||||||
|
* Introduced :lookup:`geom_type` lookup to allow filtering by geometry type (:ticket:`28696`)
|
||||||
|
|
||||||
:mod:`django.contrib.messages`
|
:mod:`django.contrib.messages`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -4,14 +4,31 @@ import re
|
|||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.contrib.gis.db.models import GeometryField, PolygonField, functions
|
from django.contrib.gis.db.models import GeometryField, PolygonField, functions
|
||||||
from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon, fromstr
|
from django.contrib.gis.geos import (
|
||||||
|
GEOSGeometry,
|
||||||
|
LineString,
|
||||||
|
MultiLineString,
|
||||||
|
MultiPoint,
|
||||||
|
MultiPolygon,
|
||||||
|
Point,
|
||||||
|
Polygon,
|
||||||
|
fromstr,
|
||||||
|
)
|
||||||
from django.contrib.gis.measure import Area
|
from django.contrib.gis.measure import Area
|
||||||
from django.db import NotSupportedError, connection
|
from django.db import NotSupportedError, connection
|
||||||
from django.db.models import IntegerField, Sum, Value
|
from django.db.models import F, IntegerField, Sum, Value
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessAnyDBFeature, skipUnlessDBFeature
|
||||||
|
|
||||||
from ..utils import FuncTestMixin
|
from ..utils import FuncTestMixin
|
||||||
from .models import City, Country, CountryWebMercator, ManyPointModel, State, Track
|
from .models import (
|
||||||
|
City,
|
||||||
|
Country,
|
||||||
|
CountryWebMercator,
|
||||||
|
Feature,
|
||||||
|
ManyPointModel,
|
||||||
|
State,
|
||||||
|
Track,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GISFunctionsTests(FuncTestMixin, TestCase):
|
class GISFunctionsTests(FuncTestMixin, TestCase):
|
||||||
@ -845,3 +862,48 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
|
|||||||
City.objects.annotate(union=functions.GeoFunc(1, "point")).get(
|
City.objects.annotate(union=functions.GeoFunc(1, "point")).get(
|
||||||
name="Dallas"
|
name="Dallas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryTypeFunctionTests(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.features = [
|
||||||
|
Feature.objects.create(name="Point", geom=Point(0, 0)),
|
||||||
|
Feature.objects.create(name="LineString", geom=LineString((0, 0), (1, 1))),
|
||||||
|
Feature.objects.create(
|
||||||
|
name="Polygon", geom=Polygon(((0, 0), (1, 0), (1, 1), (0, 0)))
|
||||||
|
),
|
||||||
|
Feature.objects.create(
|
||||||
|
name="MultiPoint", geom=MultiPoint(Point(0, 0), Point(1, 1))
|
||||||
|
),
|
||||||
|
Feature.objects.create(
|
||||||
|
name="MultiLineString",
|
||||||
|
geom=MultiLineString(
|
||||||
|
LineString((0, 0), (1, 1)), LineString((1, 1), (2, 2))
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Feature.objects.create(
|
||||||
|
name="MultiPolygon",
|
||||||
|
geom=MultiPolygon(
|
||||||
|
Polygon(((0, 0), (1, 0), (1, 1), (0, 0))),
|
||||||
|
Polygon(((1, 1), (2, 1), (2, 2), (1, 1))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@skipUnlessAnyDBFeature("has_GeometryType_function", "has_SDO_GTYPE_function")
|
||||||
|
def test_geometry_type_transform(self):
|
||||||
|
qs = Feature.objects.annotate(geom_type=F("geom__geom_type"))
|
||||||
|
|
||||||
|
expected_results = {
|
||||||
|
"Point": "POINT",
|
||||||
|
"LineString": "LINESTRING",
|
||||||
|
"Polygon": "POLYGON",
|
||||||
|
"MultiPoint": "MULTIPOINT",
|
||||||
|
"MultiLineString": "MULTILINESTRING",
|
||||||
|
"MultiPolygon": "MULTIPOLYGON",
|
||||||
|
}
|
||||||
|
|
||||||
|
for feature in qs:
|
||||||
|
expected_type = expected_results[feature.name]
|
||||||
|
self.assertEqual(feature.geom_type.upper(), expected_type)
|
||||||
|
Loading…
Reference in New Issue
Block a user