2015-11-09 14:33:40 +08:00
|
|
|
from unittest import skipUnless
|
|
|
|
|
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
|
|
|
|
|
|
|
|
from ..utils import postgis
|
2018-01-27 18:12:11 +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)
|
|
|
|
|
|
|
|
@skipUnless(postgis, 'Only postgis has geography fields.')
|
|
|
|
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)))).first().a
|
|
|
|
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))
|
|
|
|
|
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').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'))
|
|
|
|
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))
|