Skip to content

Commit

Permalink
[fix] Deserialize id_field #272
Browse files Browse the repository at this point in the history
When serializing a model, the value of its `id_field` is written in the `id` attribute
of the GeoJSON feature.

This behaviour is however not mirrored by the deserialization logic: deserializing a
model through GeoFeatureModelSerializer ignores the `id` field set in the given GeoJSON
feature.

This commit solves this issue by mirroring the serialization logic:
- When deserializing a model, the `id` attribute of the GeoJSON feature is written as the
`id_field` of the django model.

Fixes #272

Signed-off-by: Stephane Restani <stephane.restani@picterra.ch>
  • Loading branch information
restaste committed Mar 21, 2022
1 parent e2c3365 commit f2dc812
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 0 deletions.
3 changes: 3 additions & 0 deletions rest_framework_gis/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ def unformat_geojson(self, feature):
if 'geometry' in feature:
attrs[self.Meta.geo_field] = feature['geometry']

if self.Meta.id_field and 'id' in feature:
attrs[self.Meta.id_field] = feature['id']

if self.Meta.bbox_geo_field and 'bbox' in feature:
attrs[self.Meta.bbox_geo_field] = Polygon.from_bbox(feature['bbox'])

Expand Down
11 changes: 11 additions & 0 deletions tests/django_restframework_gis_tests/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ class Meta:
fields = ('name',)


class LocationGeoFeatureWritableIdSerializer(LocationGeoFeatureSerializer):
""" default id attribute """

class Meta:
model = Location
geo_field = 'geometry'
fields = ('id', 'name', 'timestamp')

id = serializers.CharField()


class LocatedFileGeoFeatureSerializer(gis_serializers.GeoFeatureModelSerializer):
""" located file geo serializer """

Expand Down
16 changes: 16 additions & 0 deletions tests/django_restframework_gis_tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,22 @@ def test_geojson_false_id_attribute_slug(self):
with self.assertRaises(KeyError):
response.data['id']

def test_post_geojson_id_attribute(self):
self.assertEqual(Location.objects.count(), 0)
data = {
"type": "Feature",
"id": "42",
"properties": {"name": "point"},
"geometry": {"type": "Point", "coordinates": [10.1, 10.1]},
}
url = reverse('api_geojson_location_writable_id_list')
response = self.client.post(
url, data=json.dumps(data), content_type='application/json',
)
self.assertEqual(response.status_code, 201)
self.assertEqual(Location.objects.count(), 1)
self.assertEqual(Location.objects.first().id, 42)

def test_geojson_no_id_attribute_slug(self):
location = Location.objects.create(
name='noid test', geometry='POINT (10.1 10.1)'
Expand Down
5 changes: 5 additions & 0 deletions tests/django_restframework_gis_tests/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
path('<int:pk>', views.location_details, name='api_location_details'),
# geojson
path('geojson/', views.geojson_location_list, name='api_geojson_location_list'),
path(
'geojson_writable_id/',
views.geojson_location_writable_id_list,
name='api_geojson_location_writable_id_list',
),
path(
'geojson/<int:pk>/',
views.geojson_location_details,
Expand Down
11 changes: 11 additions & 0 deletions tests/django_restframework_gis_tests/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
LocationGeoFeatureNoIdSerializer,
LocationGeoFeatureSerializer,
LocationGeoFeatureSlugSerializer,
LocationGeoFeatureWritableIdSerializer,
LocationGeoSerializer,
NoneGeoFeatureMethodSerializer,
PaginatedLocationGeoSerializer,
Expand Down Expand Up @@ -57,6 +58,16 @@ class GeojsonLocationList(generics.ListCreateAPIView):
geojson_location_list = GeojsonLocationList.as_view()


class GeojsonLocationWritableIdList(generics.ListCreateAPIView):
model = Location
serializer_class = LocationGeoFeatureWritableIdSerializer
queryset = Location.objects.all()
pagination_class = GeoJsonPagination


geojson_location_writable_id_list = GeojsonLocationWritableIdList.as_view()


class GeojsonLocationContainedInBBoxList(generics.ListAPIView):
model = Location
serializer_class = LocationGeoFeatureSerializer
Expand Down

0 comments on commit f2dc812

Please sign in to comment.