2014-11-08 16:08:12 +00:00
|
|
|
import json
|
|
|
|
|
2015-04-24 15:24:07 +00:00
|
|
|
from django.contrib.gis.geos import LinearRing, Point, Polygon
|
2014-11-08 16:08:12 +00:00
|
|
|
from django.core import serializers
|
2017-05-04 14:14:35 +00:00
|
|
|
from django.test import TestCase
|
2014-11-08 16:08:12 +00:00
|
|
|
|
2015-04-24 15:24:07 +00:00
|
|
|
from .models import City, MultiFields, PennsylvaniaCity
|
2014-11-08 16:08:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
class GeoJSONSerializerTests(TestCase):
|
|
|
|
fixtures = ["initial"]
|
|
|
|
|
|
|
|
def test_builtin_serializers(self):
|
|
|
|
"""
|
|
|
|
'geojson' should be listed in available serializers.
|
|
|
|
"""
|
|
|
|
all_formats = set(serializers.get_serializer_formats())
|
|
|
|
public_formats = set(serializers.get_public_serializer_formats())
|
|
|
|
|
2023-08-22 10:42:57 +00:00
|
|
|
self.assertIn("geojson", all_formats)
|
2014-11-08 16:08:12 +00:00
|
|
|
self.assertIn("geojson", public_formats)
|
|
|
|
|
|
|
|
def test_serialization_base(self):
|
2022-02-22 09:29:38 +00:00
|
|
|
geojson = serializers.serialize("geojson", City.objects.order_by("name"))
|
2016-06-28 15:21:26 +00:00
|
|
|
geodata = json.loads(geojson)
|
2024-12-09 17:55:27 +00:00
|
|
|
self.assertEqual(list(geodata.keys()), ["type", "features"])
|
|
|
|
self.assertEqual(geodata["type"], "FeatureCollection")
|
2014-11-08 16:08:12 +00:00
|
|
|
self.assertEqual(len(geodata["features"]), len(City.objects.all()))
|
|
|
|
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Point")
|
|
|
|
self.assertEqual(geodata["features"][0]["properties"]["name"], "Chicago")
|
2022-02-22 09:29:38 +00:00
|
|
|
first_city = City.objects.order_by("name").first()
|
2022-05-28 09:33:15 +00:00
|
|
|
self.assertEqual(geodata["features"][0]["id"], first_city.pk)
|
2016-02-23 18:57:53 +00:00
|
|
|
self.assertEqual(geodata["features"][0]["properties"]["pk"], str(first_city.pk))
|
2014-11-08 16:08:12 +00:00
|
|
|
|
|
|
|
def test_geometry_field_option(self):
|
|
|
|
"""
|
|
|
|
When a model has several geometry fields, the 'geometry_field' option
|
|
|
|
can be used to specify the field to use as the 'geometry' key.
|
|
|
|
"""
|
|
|
|
MultiFields.objects.create(
|
|
|
|
city=City.objects.first(),
|
|
|
|
name="Name",
|
|
|
|
point=Point(5, 23),
|
|
|
|
poly=Polygon(LinearRing((0, 0), (0, 5), (5, 5), (5, 0), (0, 0))),
|
|
|
|
)
|
|
|
|
|
|
|
|
geojson = serializers.serialize("geojson", MultiFields.objects.all())
|
|
|
|
geodata = json.loads(geojson)
|
|
|
|
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Point")
|
|
|
|
|
2016-01-26 10:06:29 +00:00
|
|
|
geojson = serializers.serialize(
|
|
|
|
"geojson", MultiFields.objects.all(), geometry_field="poly"
|
|
|
|
)
|
|
|
|
geodata = json.loads(geojson)
|
|
|
|
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Polygon")
|
|
|
|
|
|
|
|
# geometry_field is considered even if not in fields (#26138).
|
|
|
|
geojson = serializers.serialize(
|
|
|
|
"geojson",
|
|
|
|
MultiFields.objects.all(),
|
|
|
|
geometry_field="poly",
|
|
|
|
fields=("city",),
|
|
|
|
)
|
2014-11-08 16:08:12 +00:00
|
|
|
geodata = json.loads(geojson)
|
|
|
|
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Polygon")
|
|
|
|
|
2022-05-28 09:33:15 +00:00
|
|
|
def test_id_field_option(self):
|
|
|
|
"""
|
|
|
|
By default Django uses the pk of the object as the id for a feature.
|
|
|
|
The 'id_field' option can be used to specify a different field to use
|
|
|
|
as the id.
|
|
|
|
"""
|
|
|
|
cities = City.objects.order_by("name")
|
|
|
|
geojson = serializers.serialize("geojson", cities, id_field="name")
|
|
|
|
geodata = json.loads(geojson)
|
|
|
|
self.assertEqual(geodata["features"][0]["id"], cities[0].name)
|
|
|
|
|
2014-11-08 16:08:12 +00:00
|
|
|
def test_fields_option(self):
|
|
|
|
"""
|
|
|
|
The fields option allows to define a subset of fields to be present in
|
|
|
|
the 'properties' of the generated output.
|
|
|
|
"""
|
|
|
|
PennsylvaniaCity.objects.create(
|
|
|
|
name="Mansfield", county="Tioga", point="POINT(-77.071445 41.823881)"
|
|
|
|
)
|
2016-04-08 02:04:45 +00:00
|
|
|
geojson = serializers.serialize(
|
|
|
|
"geojson",
|
|
|
|
PennsylvaniaCity.objects.all(),
|
|
|
|
fields=("county", "point"),
|
|
|
|
)
|
2014-11-08 16:08:12 +00:00
|
|
|
geodata = json.loads(geojson)
|
|
|
|
self.assertIn("county", geodata["features"][0]["properties"])
|
|
|
|
self.assertNotIn("founded", geodata["features"][0]["properties"])
|
2016-02-23 18:57:53 +00:00
|
|
|
self.assertNotIn("pk", geodata["features"][0]["properties"])
|
2014-11-08 16:08:12 +00:00
|
|
|
|
|
|
|
def test_srid_option(self):
|
|
|
|
geojson = serializers.serialize(
|
2022-02-22 09:29:38 +00:00
|
|
|
"geojson", City.objects.order_by("name"), srid=2847
|
2014-11-08 16:08:12 +00:00
|
|
|
)
|
|
|
|
geodata = json.loads(geojson)
|
2021-03-23 08:16:33 +00:00
|
|
|
coordinates = geodata["features"][0]["geometry"]["coordinates"]
|
|
|
|
# Different PROJ versions use different transformations, all are
|
|
|
|
# correct as having a 1 meter accuracy.
|
|
|
|
self.assertAlmostEqual(coordinates[0], 1564802, -1)
|
|
|
|
self.assertAlmostEqual(coordinates[1], 5613214, -1)
|
2014-11-08 16:08:12 +00:00
|
|
|
|
|
|
|
def test_deserialization_exception(self):
|
|
|
|
"""
|
|
|
|
GeoJSON cannot be deserialized.
|
|
|
|
"""
|
|
|
|
with self.assertRaises(serializers.base.SerializerDoesNotExist):
|
|
|
|
serializers.deserialize("geojson", "{}")
|