summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamir Shah <solaris.smoke@gmail.com>2022-05-28 12:33:15 +0300
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-06-01 19:11:26 +0200
commit6f73eb9d90cfec684529aab48d517e3d6449ba8c (patch)
tree4c25ff654a55ac837acc0621c8e473d4093f5d8d
parent9a3b7e5e2be751d28b8782ad23a63e1c75f27e24 (diff)
Fixed #33742 -- Added id to GeoJSON serializer.
-rw-r--r--django/contrib/gis/serializers/geojson.py2
-rw-r--r--docs/ref/contrib/gis/serializers.txt9
-rw-r--r--docs/releases/4.2.txt4
-rw-r--r--tests/gis_tests/geoapp/test_serializers.py12
4 files changed, 26 insertions, 1 deletions
diff --git a/django/contrib/gis/serializers/geojson.py b/django/contrib/gis/serializers/geojson.py
index 865e90caec..072ee9dc48 100644
--- a/django/contrib/gis/serializers/geojson.py
+++ b/django/contrib/gis/serializers/geojson.py
@@ -13,6 +13,7 @@ class Serializer(JSONSerializer):
def _init_options(self):
super()._init_options()
self.geometry_field = self.json_kwargs.pop("geometry_field", None)
+ self.id_field = self.json_kwargs.pop("id_field", None)
self.srid = self.json_kwargs.pop("srid", 4326)
if (
self.selected_fields is not None
@@ -46,6 +47,7 @@ class Serializer(JSONSerializer):
def get_dump_object(self, obj):
data = {
"type": "Feature",
+ "id": obj.pk if self.id_field is None else getattr(obj, self.id_field),
"properties": self._current,
}
if (
diff --git a/docs/ref/contrib/gis/serializers.txt b/docs/ref/contrib/gis/serializers.txt
index 5ab3e56704..f3d465c385 100644
--- a/docs/ref/contrib/gis/serializers.txt
+++ b/docs/ref/contrib/gis/serializers.txt
@@ -25,6 +25,9 @@ serializer accepts the following additional option when it is called by
have a model with more than one geometry field and you don't want to use the
first defined geometry field (by default, the first geometry field is picked).
+* ``id_field``: A string containing the name of a field to use for the ``id``
+ key of the GeoJSON feature. By default, the primary key of objects is used.
+
* ``srid``: The SRID to use for the ``geometry`` content. Defaults to 4326
(WGS 84).
@@ -52,6 +55,7 @@ Would output::
'features': [
{
'type': 'Feature',
+ 'id': 1,
'geometry': {
'type': 'Point',
'coordinates': [-87.650175, 41.850385]
@@ -66,3 +70,8 @@ Would output::
When the ``fields`` parameter is not specified, the ``geojson`` serializer adds
a ``pk`` key to the ``properties`` dictionary with the primary key of the
object as the value.
+
+.. versionchanged:: 4.2
+
+ The ``id`` key for serialized features was added. Also, the ``id_field``
+ option was added to the ``geojson`` serializer.
diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt
index 0d95f68654..0c80c5b103 100644
--- a/docs/releases/4.2.txt
+++ b/docs/releases/4.2.txt
@@ -53,7 +53,9 @@ Minor features
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
-* ...
+* The :doc:`GeoJSON serializer </ref/contrib/gis/serializers>` now outputs the
+ ``id`` key for serialized features, which defaults to the primary key of
+ objects.
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/gis_tests/geoapp/test_serializers.py b/tests/gis_tests/geoapp/test_serializers.py
index 44066daee9..ecff6e6471 100644
--- a/tests/gis_tests/geoapp/test_serializers.py
+++ b/tests/gis_tests/geoapp/test_serializers.py
@@ -27,6 +27,7 @@ class GeoJSONSerializerTests(TestCase):
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Point")
self.assertEqual(geodata["features"][0]["properties"]["name"], "Chicago")
first_city = City.objects.order_by("name").first()
+ self.assertEqual(geodata["features"][0]["id"], first_city.pk)
self.assertEqual(geodata["features"][0]["properties"]["pk"], str(first_city.pk))
def test_geometry_field_option(self):
@@ -61,6 +62,17 @@ class GeoJSONSerializerTests(TestCase):
geodata = json.loads(geojson)
self.assertEqual(geodata["features"][0]["geometry"]["type"], "Polygon")
+ 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)
+
def test_fields_option(self):
"""
The fields option allows to define a subset of fields to be present in