mirror of
https://github.com/django/django.git
synced 2024-12-22 09:05:43 +00: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 (
|
||||
BinaryField,
|
||||
BooleanField,
|
||||
CharField,
|
||||
FloatField,
|
||||
Func,
|
||||
IntegerField,
|
||||
@ -421,6 +422,37 @@ class Intersection(OracleToleranceMixin, GeomOutputGeoFunc):
|
||||
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
|
||||
class IsEmpty(GeoFuncMixin, Transform):
|
||||
lookup_name = "isempty"
|
||||
|
@ -692,6 +692,34 @@ PostGIS equivalent:
|
||||
|
||||
.. _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
|
||||
================
|
||||
|
||||
|
@ -99,6 +99,7 @@ Minor features
|
||||
:attr:`.OGRGeometry.has_curve` property, and the
|
||||
:meth:`.OGRGeometry.get_linear_geometry` and
|
||||
:meth:`.OGRGeometry.get_curve_geometry` methods.
|
||||
* Introduced :lookup:`geom_type` lookup to allow filtering by geometry type (:ticket:`28696`)
|
||||
|
||||
:mod:`django.contrib.messages`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -4,14 +4,31 @@ import re
|
||||
from decimal import Decimal
|
||||
|
||||
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.db import NotSupportedError, connection
|
||||
from django.db.models import IntegerField, Sum, Value
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.db.models import F, IntegerField, Sum, Value
|
||||
from django.test import TestCase, skipUnlessAnyDBFeature, skipUnlessDBFeature
|
||||
|
||||
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):
|
||||
@ -845,3 +862,48 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
|
||||
City.objects.annotate(union=functions.GeoFunc(1, "point")).get(
|
||||
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