Browse Source

Fixed #33742 -- Added id to GeoJSON serializer.

Samir Shah 2 years ago
parent
commit
6f73eb9d90

+ 2 - 0
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 (

+ 9 - 0
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.

+ 3 - 1
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`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ 12 - 0
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