From 58ec8d0bb94f05837a43116acbf3c632280536e8 Mon Sep 17 00:00:00 2001 From: Adil Hemache Date: Thu, 5 Nov 2020 17:15:30 +0100 Subject: [PATCH 1/5] [fix] attribute error when trying to get bounding box from a method field value --- rest_framework_gis/serializers.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) 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) From 1d57899fceb19eaf71cb812c50c46d3de6dc2dcd Mon Sep 17 00:00:00 2001 From: Adil Hemache Date: Thu, 5 Nov 2020 17:17:42 +0100 Subject: [PATCH 2/5] [qa] Test bounding box calculation when using method field for geo field --- .../serializers.py | 26 +++++++++++++++++++ .../test_bbox.py | 16 ++++++++++++ tests/django_restframework_gis_tests/urls.py | 10 +++++++ tests/django_restframework_gis_tests/views.py | 20 ++++++++++++++ 4 files changed, 72 insertions(+) diff --git a/tests/django_restframework_gis_tests/serializers.py b/tests/django_restframework_gis_tests/serializers.py index 1646652e..3dd3ac0a 100644 --- a/tests/django_restframework_gis_tests/serializers.py +++ b/tests/django_restframework_gis_tests/serializers.py @@ -140,6 +140,32 @@ 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..ec920488 100644 --- a/tests/django_restframework_gis_tests/test_bbox.py +++ b/tests/django_restframework_gis_tests/test_bbox.py @@ -22,6 +22,8 @@ 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 +89,20 @@ 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..08e0fce9 100644 --- a/tests/django_restframework_gis_tests/views.py +++ b/tests/django_restframework_gis_tests/views.py @@ -18,6 +18,8 @@ LocationGeoFeatureBboxSerializer, LocationGeoFeatureFalseIdSerializer, LocationGeoFeatureMethodSerializer, + LocationGeoFeatureMethodAutoBboxSerializer, + LocationGeoFeatureMethodManualBboxSerializer, LocationGeoFeatureNoIdSerializer, LocationGeoFeatureSerializer, LocationGeoFeatureSlugSerializer, @@ -240,6 +242,24 @@ 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 From 191209bfb843a748c56800e0903a79331acb5337 Mon Sep 17 00:00:00 2001 From: Adil Hemache Date: Thu, 5 Nov 2020 21:28:05 +0100 Subject: [PATCH 3/5] [qa] Format code --- .../serializers.py | 8 ++++++-- .../test_bbox.py | 18 +++++++++++++----- tests/django_restframework_gis_tests/views.py | 10 +++++++--- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tests/django_restframework_gis_tests/serializers.py b/tests/django_restframework_gis_tests/serializers.py index 3dd3ac0a..7f5fdd20 100644 --- a/tests/django_restframework_gis_tests/serializers.py +++ b/tests/django_restframework_gis_tests/serializers.py @@ -140,7 +140,9 @@ class Meta: exclude = [] -class LocationGeoFeatureMethodAutoBboxSerializer(gis_serializers.GeoFeatureModelSerializer): +class LocationGeoFeatureMethodAutoBboxSerializer( + gis_serializers.GeoFeatureModelSerializer +): new_geometry = gis_serializers.GeometrySerializerMethodField() class Meta: @@ -153,7 +155,9 @@ def get_new_geometry(self, obj): return obj.geometry -class LocationGeoFeatureMethodManualBboxSerializer(gis_serializers.GeoFeatureModelSerializer): +class LocationGeoFeatureMethodManualBboxSerializer( + gis_serializers.GeoFeatureModelSerializer +): new_geometry = gis_serializers.GeometrySerializerMethodField() class Meta: diff --git a/tests/django_restframework_gis_tests/test_bbox.py b/tests/django_restframework_gis_tests/test_bbox.py index ec920488..22f21000 100644 --- a/tests/django_restframework_gis_tests/test_bbox.py +++ b/tests/django_restframework_gis_tests/test_bbox.py @@ -22,8 +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') + 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( @@ -91,14 +95,18 @@ def test_get_autogenerated_location_bbox_geojson(self): 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) + 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) + 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) diff --git a/tests/django_restframework_gis_tests/views.py b/tests/django_restframework_gis_tests/views.py index 08e0fce9..f5d1b220 100644 --- a/tests/django_restframework_gis_tests/views.py +++ b/tests/django_restframework_gis_tests/views.py @@ -17,9 +17,9 @@ LocatedFileGeoFeatureSerializer, LocationGeoFeatureBboxSerializer, LocationGeoFeatureFalseIdSerializer, - LocationGeoFeatureMethodSerializer, LocationGeoFeatureMethodAutoBboxSerializer, LocationGeoFeatureMethodManualBboxSerializer, + LocationGeoFeatureMethodSerializer, LocationGeoFeatureNoIdSerializer, LocationGeoFeatureSerializer, LocationGeoFeatureSlugSerializer, @@ -248,7 +248,9 @@ class GeojsonLocationMethodFieldAutoBboxList(generics.ListCreateAPIView): queryset = Location.objects.all() -geojson_location_method_field_auto_bbox_list = GeojsonLocationMethodFieldAutoBboxList.as_view() +geojson_location_method_field_auto_bbox_list = ( + GeojsonLocationMethodFieldAutoBboxList.as_view() +) class GeojsonLocationMethodFieldManualBboxList(generics.ListCreateAPIView): @@ -257,7 +259,9 @@ class GeojsonLocationMethodFieldManualBboxList(generics.ListCreateAPIView): queryset = Location.objects.all() -geojson_location_method_field_manual_bbox_list = GeojsonLocationMethodFieldManualBboxList.as_view() +geojson_location_method_field_manual_bbox_list = ( + GeojsonLocationMethodFieldManualBboxList.as_view() +) class GeojsonNullableDetails(generics.RetrieveUpdateDestroyAPIView): From 004073965720b6ba4e7cd625a4fa31804c2be1ba Mon Sep 17 00:00:00 2001 From: Adil Hemache Date: Wed, 11 Nov 2020 20:07:02 +0100 Subject: [PATCH 4/5] [qa] Change PostgreSQL database port back to default value & Allow peer authentication for user "postgres" --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1b4845e7..b6693102 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,10 @@ before_install: - sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y - sudo apt-get update -q - sudo apt-get install binutils libproj-dev gdal-bin -y + - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/12/main/postgresql.conf + - sudo sed -i -e '/local.*peer/s/postgres/all/' -e 's/peer\|md5/trust/g' /etc/postgresql/12/main/pg_hba.conf + - sudo systemctl restart postgresql@12-main + - sudo cat /var/log/postgresql/postgresql-12-main.log - pip install -U pip setuptools wheel - pip install -U -r requirements-test.txt install: From 84cd6426940aef4637a77ae130fc268b3686db4e Mon Sep 17 00:00:00 2001 From: Hemache Adil Date: Wed, 2 Dec 2020 14:08:29 +0100 Subject: [PATCH 5/5] [qa] Rollback CI PostgreSQL default port fix --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b6693102..1b4845e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,10 +37,6 @@ before_install: - sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y - sudo apt-get update -q - sudo apt-get install binutils libproj-dev gdal-bin -y - - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/12/main/postgresql.conf - - sudo sed -i -e '/local.*peer/s/postgres/all/' -e 's/peer\|md5/trust/g' /etc/postgresql/12/main/pg_hba.conf - - sudo systemctl restart postgresql@12-main - - sudo cat /var/log/postgresql/postgresql-12-main.log - pip install -U pip setuptools wheel - pip install -U -r requirements-test.txt install: