2017-04-11 01:26:26 +08:00
|
|
|
from django.contrib.gis.db.models import F, GeometryField, Value, functions
|
2015-11-09 14:33:40 +08:00
|
|
|
from django.contrib.gis.geos import Point, Polygon
|
2017-04-11 01:26:26 +08:00
|
|
|
from django.db import connection
|
2018-05-31 22:38:42 +08:00
|
|
|
from django.db.models import Count, Min
|
2015-11-09 14:33:40 +08:00
|
|
|
from django.test import TestCase, skipUnlessDBFeature
|
|
|
|
|
2019-03-04 02:33:48 +08:00
|
|
|
from .models import City, ManyPointModel, MultiFields
|
2015-11-09 14:33:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
class GeoExpressionsTests(TestCase):
|
|
|
|
fixtures = ["initial"]
|
|
|
|
|
|
|
|
def test_geometry_value_annotation(self):
|
|
|
|
p = Point(1, 1, srid=4326)
|
|
|
|
point = City.objects.annotate(p=Value(p, GeometryField(srid=4326))).first().p
|
|
|
|
self.assertEqual(point, p)
|
|
|
|
|
|
|
|
@skipUnlessDBFeature("supports_transform")
|
|
|
|
def test_geometry_value_annotation_different_srid(self):
|
|
|
|
p = Point(1, 1, srid=32140)
|
|
|
|
point = City.objects.annotate(p=Value(p, GeometryField(srid=4326))).first().p
|
|
|
|
self.assertTrue(point.equals_exact(p.transform(4326, clone=True), 10**-5))
|
|
|
|
self.assertEqual(point.srid, 4326)
|
|
|
|
|
2020-11-14 22:08:30 +08:00
|
|
|
@skipUnlessDBFeature("supports_geography")
|
2015-11-09 14:33:40 +08:00
|
|
|
def test_geography_value(self):
|
|
|
|
p = Polygon(((1, 1), (1, 2), (2, 2), (2, 1), (1, 1)))
|
|
|
|
area = (
|
|
|
|
City.objects.annotate(
|
|
|
|
a=functions.Area(Value(p, GeometryField(srid=4326, geography=True)))
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2015-11-09 14:33:40 +08:00
|
|
|
.first()
|
|
|
|
.a
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2015-11-09 14:33:40 +08:00
|
|
|
self.assertAlmostEqual(area.sq_km, 12305.1, 0)
|
2017-04-11 01:26:26 +08:00
|
|
|
|
|
|
|
def test_update_from_other_field(self):
|
|
|
|
p1 = Point(1, 1, srid=4326)
|
|
|
|
p2 = Point(2, 2, srid=4326)
|
|
|
|
obj = ManyPointModel.objects.create(
|
|
|
|
point1=p1,
|
|
|
|
point2=p2,
|
|
|
|
point3=p2.transform(3857, clone=True),
|
|
|
|
)
|
|
|
|
# Updating a point to a point of the same SRID.
|
|
|
|
ManyPointModel.objects.filter(pk=obj.pk).update(point2=F("point1"))
|
|
|
|
obj.refresh_from_db()
|
|
|
|
self.assertEqual(obj.point2, p1)
|
|
|
|
# Updating a point to a point with a different SRID.
|
|
|
|
if connection.features.supports_transform:
|
|
|
|
ManyPointModel.objects.filter(pk=obj.pk).update(point3=F("point1"))
|
|
|
|
obj.refresh_from_db()
|
|
|
|
self.assertTrue(
|
|
|
|
obj.point3.equals_exact(p1.transform(3857, clone=True), 0.1)
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2017-04-11 01:26:26 +08:00
|
|
|
|
2018-01-27 18:12:11 +08:00
|
|
|
def test_multiple_annotation(self):
|
|
|
|
multi_field = MultiFields.objects.create(
|
|
|
|
point=Point(1, 1),
|
|
|
|
city=City.objects.get(name="Houston"),
|
|
|
|
poly=Polygon(((1, 1), (1, 2), (2, 2), (2, 1), (1, 1))),
|
|
|
|
)
|
|
|
|
qs = (
|
|
|
|
City.objects.values("name")
|
2022-06-13 09:08:21 +08:00
|
|
|
.order_by("name")
|
2018-01-27 18:12:11 +08:00
|
|
|
.annotate(
|
2018-05-31 22:38:42 +08:00
|
|
|
distance=Min(
|
|
|
|
functions.Distance("multifields__point", multi_field.city.point)
|
|
|
|
),
|
2018-01-27 18:12:11 +08:00
|
|
|
)
|
|
|
|
.annotate(count=Count("multifields"))
|
2022-02-04 03:24:19 +08:00
|
|
|
)
|
2018-01-27 18:12:11 +08:00
|
|
|
self.assertTrue(qs.first())
|
|
|
|
|
2017-04-11 01:26:26 +08:00
|
|
|
@skipUnlessDBFeature("has_Translate_function")
|
|
|
|
def test_update_with_expression(self):
|
|
|
|
city = City.objects.create(point=Point(1, 1, srid=4326))
|
|
|
|
City.objects.filter(pk=city.pk).update(point=functions.Translate("point", 1, 1))
|
|
|
|
city.refresh_from_db()
|
|
|
|
self.assertEqual(city.point, Point(2, 2, srid=4326))
|