From 49bcc85116e34022d3602ec11c244bf3b2bb8f8e Mon Sep 17 00:00:00 2001 From: Dana Lambert Date: Fri, 22 Oct 2021 16:01:38 +1300 Subject: [PATCH] Add api endpoints for collecting location details - includes soil order name and code, ecological district, ecological region and address from linz --- backend/right_tree/api/filters.py | 26 ++++++++--- backend/right_tree/api/serializers.py | 28 +++++++++++- backend/right_tree/api/views.py | 63 +++++++++++++++++++++++++-- backend/right_tree/urls.py | 3 ++ 4 files changed, 107 insertions(+), 13 deletions(-) diff --git a/backend/right_tree/api/filters.py b/backend/right_tree/api/filters.py index a6bada7..21d291d 100644 --- a/backend/right_tree/api/filters.py +++ b/backend/right_tree/api/filters.py @@ -1,20 +1,16 @@ import json -from django.contrib.gis.geos import Point +from django.http import Http404 from django.db.models import Q from .models import EcologicalRegion, EcologicalDistrictLayer, SoilOrder, SoilVariant - +from .utils import get_point_from_coordinates def coordinate_filter(request, queryset): coordinates = request.query_params.get('coordinates') if coordinates is not None: - coordinates_json = json.loads(coordinates) - pnt = Point(coordinates_json["lng"], - coordinates_json["lat"], srid=4326) - pnt.transform(2193) - + pnt = get_point_from_coordinates(coordinates) filtered_regions = EcologicalRegion.objects.filter( ecologicaldistrictlayer__geom__intersects=pnt).values_list('id', flat=True) filtered_soil_orders = SoilOrder.objects.filter( @@ -37,3 +33,19 @@ def soil_variant_filter(request, queryset): return queryset.filter(soil_variants__in=soil_variant_ids).distinct() return queryset + + +def soil_order_coordinate_filter(coordinates): + pnt = get_point_from_coordinates(coordinates) + try: + return SoilOrder.objects.filter(soillayer__geom__intersects=pnt) + except SoilOrder.DoesNotExist: + raise Http404(f"Soil Order cannot be found for point {pnt}") + + +def ecological_district_coordinate_filter(coordinates): + pnt = get_point_from_coordinates(coordinates) + try: + return EcologicalDistrictLayer.objects.filter(geom__intersects=pnt) + except EcologicalDistrictLayer.DoesNotExist: + raise Http404(f"Ecological district layer cannot be found for point {pnt}") diff --git a/backend/right_tree/api/serializers.py b/backend/right_tree/api/serializers.py index 4e81450..eb75888 100644 --- a/backend/right_tree/api/serializers.py +++ b/backend/right_tree/api/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from right_tree.api.models import Plant, ToleranceLevel, SoilOrder, SoilVariant, EcologicalRegion +from right_tree.api.models import Plant, ToleranceLevel, SoilOrder, SoilVariant, EcologicalRegion, EcologicalDistrictLayer class ToleranceLevelSerializer(serializers.HyperlinkedModelSerializer): @@ -14,10 +14,23 @@ class EcologicalRegionSerializer(serializers.HyperlinkedModelSerializer): fields = ['name'] +class EcologicalDistrictLayerSerializer(serializers.HyperlinkedModelSerializer): + ecological_district = serializers.CharField(max_length=50, source='ecologic_1') + ecological_region = serializers.CharField( + max_length=50, source='ecologic_2') + + class Meta: + model = EcologicalDistrictLayer + fields = ['ecological_district', 'ecological_region'] + + class SoilOrderSerializer(serializers.HyperlinkedModelSerializer): + soil_name = serializers.CharField(max_length=50, source='name') + soil_code = serializers.CharField(max_length=1, source='code') + class Meta: model = SoilOrder - fields = ['name'] + fields = ['soil_name', 'soil_code'] class SoilVariantSerializer(serializers.HyperlinkedModelSerializer): @@ -26,6 +39,13 @@ class SoilVariantSerializer(serializers.HyperlinkedModelSerializer): fields = ['name'] +class LocationDetailsSerializer(serializers.Serializer): + ecologic_1 = serializers.CharField(max_length=50) + ecologic_2 = serializers.CharField(max_length=50) + code = serializers.CharField(max_length=1) + name = serializers.CharField(max_length=50) + + class PlantSerializer(serializers.HyperlinkedModelSerializer): id = serializers.ReadOnlyField() water_tolerance = ToleranceLevelSerializer() @@ -39,3 +59,7 @@ class PlantSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Plant fields = '__all__' + + +class AddressSerializer(serializers.Serializer): + full_address = serializers.CharField(max_length=500) diff --git a/backend/right_tree/api/views.py b/backend/right_tree/api/views.py index eb7f952..f09458b 100644 --- a/backend/right_tree/api/views.py +++ b/backend/right_tree/api/views.py @@ -1,7 +1,17 @@ +import json + +from django.contrib.gis.geos import Point +from django.contrib.gis.db import models +from django.http import HttpResponseBadRequest + from rest_framework import viewsets -from right_tree.api.models import Plant -from right_tree.api.serializers import PlantSerializer -from .filters import coordinate_filter, soil_variant_filter +from rest_framework.response import Response + +from right_tree.api.models import Plant, EcologicalDistrictLayer, SoilOrder +from right_tree.api.serializers import PlantSerializer, SoilOrderSerializer, EcologicalDistrictLayerSerializer, AddressSerializer + +from .filters import * +from .utils import get_address_from_coordinates class PlantViewSet(viewsets.ModelViewSet): """ @@ -19,4 +29,49 @@ class PlantViewSet(viewsets.ModelViewSet): queryset = soil_variant_filter(self.request, queryset) return queryset - \ No newline at end of file + +class SoilOrderViewSet(viewsets.ModelViewSet): + """ + Filtered viewset for soil details. + """ + serializer_class = SoilOrderSerializer + + def get_queryset(self): + """ Filtering soil order query set by coordinate parameters in the URL. + """ + coordinates = self.request.query_params.get('coordinates') + if coordinates is not None: + return soil_order_coordinate_filter(coordinates) + + return SoilOrder.objects.all() + + +class EcologicalDistrictViewSet(viewsets.ModelViewSet): + """ + Filtered viewset for ecological district/region details. + """ + serializer_class = EcologicalDistrictLayerSerializer + + def get_queryset(self): + """ Filtering ecological district/region query set by coordinate parameters in the URL. + """ + coordinates = self.request.query_params.get('coordinates') + if coordinates is not None: + return ecological_district_coordinate_filter(coordinates) + + return EcologicalDistrictLayer.objects.all() + + +class LINZPropertyViewSet(viewsets.ViewSet): + """ + Filtered viewset for ecological district/region details. + """ + + def list(self, request): + coordinates = self.request.query_params.get('coordinates') + if coordinates is not None: + address_data = get_address_from_coordinates(coordinates) + serializer = AddressSerializer(address_data) + return Response(serializer.data) + else: + return HttpResponseBadRequest("No coordinate given.") diff --git a/backend/right_tree/urls.py b/backend/right_tree/urls.py index 2b30f2d..496e92d 100644 --- a/backend/right_tree/urls.py +++ b/backend/right_tree/urls.py @@ -21,6 +21,9 @@ from right_tree.api import views router = routers.DefaultRouter() router.register(r'plants', views.PlantViewSet) +router.register(r'soil', views.SoilOrderViewSet, basename='soil') +router.register(r'ecologicaldistrict', views.EcologicalDistrictViewSet, basename='ecologicaldistrict') +router.register(r'address', views.LINZPropertyViewSet, basename='address') urlpatterns = [ path('admin/', admin.site.urls),