diff --git a/rest_framework_gis/serializers.py b/rest_framework_gis/serializers.py index 0ea8545b..f5eacfce 100644 --- a/rest_framework_gis/serializers.py +++ b/rest_framework_gis/serializers.py @@ -6,6 +6,7 @@ LIST_SERIALIZER_KWARGS, ListSerializer, ModelSerializer, + SerializerMethodField, ) from .fields import GeometryField, GeometrySerializerMethodField # noqa @@ -132,7 +133,12 @@ def to_representation(self, instance): # MUST be present in output according to GeoJSON spec field = self.fields[self.Meta.geo_field] geo_value = field.get_attribute(instance) - feature["geometry"] = field.to_representation(geo_value) + if isinstance(field, SerializerMethodField): + method = getattr(field.parent, field.method_name) + geo_value = method(instance) + feature["geometry"] = field.to_representation(instance) + else: + feature["geometry"] = field.to_representation(geo_value) processed_fields.add(self.Meta.geo_field) # Bounding Box @@ -143,7 +149,11 @@ def to_representation(self, instance): # otherwise it can be determined via another field elif self.Meta.bbox_geo_field: field = self.fields[self.Meta.bbox_geo_field] - value = field.get_attribute(instance) + if isinstance(field, SerializerMethodField): + method = getattr(field.parent, field.method_name) + value = method(instance) + else: + value = field.get_attribute(instance) feature["bbox"] = value.extent if hasattr(value, 'extent') else None processed_fields.add(self.Meta.bbox_geo_field) diff --git a/tests/django_restframework_gis_tests/serializers.py b/tests/django_restframework_gis_tests/serializers.py index 1646652e..7f5fdd20 100644 --- a/tests/django_restframework_gis_tests/serializers.py +++ b/tests/django_restframework_gis_tests/serializers.py @@ -140,6 +140,36 @@ class Meta: exclude = [] +class LocationGeoFeatureMethodAutoBboxSerializer( + gis_serializers.GeoFeatureModelSerializer +): + new_geometry = gis_serializers.GeometrySerializerMethodField() + + class Meta: + model = Location + geo_field = 'new_geometry' + auto_bbox = True + exclude = [] + + def get_new_geometry(self, obj): + return obj.geometry + + +class LocationGeoFeatureMethodManualBboxSerializer( + gis_serializers.GeoFeatureModelSerializer +): + new_geometry = gis_serializers.GeometrySerializerMethodField() + + class Meta: + model = Location + geo_field = 'new_geometry' + bbox_geo_field = 'new_geometry' + exclude = [] + + def get_new_geometry(self, obj): + return obj.geometry + + class NoneGeoFeatureMethodSerializer(gis_serializers.GeoFeatureModelSerializer): new_geometry = gis_serializers.GeometrySerializerMethodField() diff --git a/tests/django_restframework_gis_tests/test_bbox.py b/tests/django_restframework_gis_tests/test_bbox.py index f3affb89..22f21000 100644 --- a/tests/django_restframework_gis_tests/test_bbox.py +++ b/tests/django_restframework_gis_tests/test_bbox.py @@ -22,6 +22,12 @@ class TestRestFrameworkGisBBox(TestCase): def setUp(self): self.geojson_boxedlocation_list_url = reverse('api_geojson_boxedlocation_list') self.geojson_location_bbox_list_url = reverse('api_geojson_location_bbox_list') + self.geojson_location_method_field_auto_bbox_list_url = reverse( + 'api_geojson_location_method_field_auto_bbox_list' + ) + self.geojson_location_method_field_manual_bbox_list_url = reverse( + 'api_geojson_location_method_field_manual_bbox_list' + ) def _create_locations(self): self.bl1 = BoxedLocation.objects.create( @@ -87,6 +93,24 @@ def test_get_autogenerated_location_bbox_geojson(self): self.assertEqual(len(response.data['features']), 1) self.assertEqual(response.data['features'][0]['bbox'], self.l1.geometry.extent) + def test_get_autogenerated_location_auto_bbox_geojson_with_method_field(self): + self._create_locations() + response = self.client.get( + self.geojson_location_method_field_auto_bbox_list_url + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data['features']), 1) + self.assertEqual(response.data['features'][0]['bbox'], self.l1.geometry.extent) + + def test_get_autogenerated_location_manual_bbox_geojson_with_method_field(self): + self._create_locations() + response = self.client.get( + self.geojson_location_method_field_manual_bbox_list_url + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.data['features']), 1) + self.assertEqual(response.data['features'][0]['bbox'], self.l1.geometry.extent) + def test_bbox_improperly_configured(self): self._create_locations() diff --git a/tests/django_restframework_gis_tests/urls.py b/tests/django_restframework_gis_tests/urls.py index 3958d414..5d6a1f27 100644 --- a/tests/django_restframework_gis_tests/urls.py +++ b/tests/django_restframework_gis_tests/urls.py @@ -65,6 +65,16 @@ views.geojson_location_bbox_list, name='api_geojson_location_bbox_list', ), + url( + r'^geojson-location-method-field-auto-bbox/$', + views.geojson_location_method_field_auto_bbox_list, + name='api_geojson_location_method_field_auto_bbox_list', + ), + url( + r'^geojson-location-method-field-manual-bbox/$', + views.geojson_location_method_field_manual_bbox_list, + name='api_geojson_location_method_field_manual_bbox_list', + ), # Filters url( r'^filters/contained_in_bbox$', diff --git a/tests/django_restframework_gis_tests/views.py b/tests/django_restframework_gis_tests/views.py index 179660b2..f5d1b220 100644 --- a/tests/django_restframework_gis_tests/views.py +++ b/tests/django_restframework_gis_tests/views.py @@ -17,6 +17,8 @@ LocatedFileGeoFeatureSerializer, LocationGeoFeatureBboxSerializer, LocationGeoFeatureFalseIdSerializer, + LocationGeoFeatureMethodAutoBboxSerializer, + LocationGeoFeatureMethodManualBboxSerializer, LocationGeoFeatureMethodSerializer, LocationGeoFeatureNoIdSerializer, LocationGeoFeatureSerializer, @@ -240,6 +242,28 @@ class GeojsonLocationBboxList(generics.ListCreateAPIView): geojson_location_bbox_list = GeojsonLocationBboxList.as_view() +class GeojsonLocationMethodFieldAutoBboxList(generics.ListCreateAPIView): + model = Location + serializer_class = LocationGeoFeatureMethodAutoBboxSerializer + queryset = Location.objects.all() + + +geojson_location_method_field_auto_bbox_list = ( + GeojsonLocationMethodFieldAutoBboxList.as_view() +) + + +class GeojsonLocationMethodFieldManualBboxList(generics.ListCreateAPIView): + model = Location + serializer_class = LocationGeoFeatureMethodManualBboxSerializer + queryset = Location.objects.all() + + +geojson_location_method_field_manual_bbox_list = ( + GeojsonLocationMethodFieldManualBboxList.as_view() +) + + class GeojsonNullableDetails(generics.RetrieveUpdateDestroyAPIView): model = Location serializer_class = LocationGeoFeatureSerializer