Add api endpoints for collecting location details

- includes soil order name and code, ecological district, ecological region and address from linz
This commit is contained in:
Dana Lambert 2021-10-22 16:01:38 +13:00
parent 2302ed6fc6
commit 49bcc85116
4 changed files with 107 additions and 13 deletions

View file

@ -1,20 +1,16 @@
import json import json
from django.contrib.gis.geos import Point from django.http import Http404
from django.db.models import Q from django.db.models import Q
from .models import EcologicalRegion, EcologicalDistrictLayer, SoilOrder, SoilVariant from .models import EcologicalRegion, EcologicalDistrictLayer, SoilOrder, SoilVariant
from .utils import get_point_from_coordinates
def coordinate_filter(request, queryset): def coordinate_filter(request, queryset):
coordinates = request.query_params.get('coordinates') coordinates = request.query_params.get('coordinates')
if coordinates is not None: if coordinates is not None:
coordinates_json = json.loads(coordinates) pnt = get_point_from_coordinates(coordinates)
pnt = Point(coordinates_json["lng"],
coordinates_json["lat"], srid=4326)
pnt.transform(2193)
filtered_regions = EcologicalRegion.objects.filter( filtered_regions = EcologicalRegion.objects.filter(
ecologicaldistrictlayer__geom__intersects=pnt).values_list('id', flat=True) ecologicaldistrictlayer__geom__intersects=pnt).values_list('id', flat=True)
filtered_soil_orders = SoilOrder.objects.filter( 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.filter(soil_variants__in=soil_variant_ids).distinct()
return queryset 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}")

View file

@ -1,5 +1,5 @@
from rest_framework import serializers 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): class ToleranceLevelSerializer(serializers.HyperlinkedModelSerializer):
@ -14,10 +14,23 @@ class EcologicalRegionSerializer(serializers.HyperlinkedModelSerializer):
fields = ['name'] 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): class SoilOrderSerializer(serializers.HyperlinkedModelSerializer):
soil_name = serializers.CharField(max_length=50, source='name')
soil_code = serializers.CharField(max_length=1, source='code')
class Meta: class Meta:
model = SoilOrder model = SoilOrder
fields = ['name'] fields = ['soil_name', 'soil_code']
class SoilVariantSerializer(serializers.HyperlinkedModelSerializer): class SoilVariantSerializer(serializers.HyperlinkedModelSerializer):
@ -26,6 +39,13 @@ class SoilVariantSerializer(serializers.HyperlinkedModelSerializer):
fields = ['name'] 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): class PlantSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.ReadOnlyField() id = serializers.ReadOnlyField()
water_tolerance = ToleranceLevelSerializer() water_tolerance = ToleranceLevelSerializer()
@ -39,3 +59,7 @@ class PlantSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = Plant model = Plant
fields = '__all__' fields = '__all__'
class AddressSerializer(serializers.Serializer):
full_address = serializers.CharField(max_length=500)

View file

@ -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 rest_framework import viewsets
from right_tree.api.models import Plant from rest_framework.response import Response
from right_tree.api.serializers import PlantSerializer
from .filters import coordinate_filter, soil_variant_filter 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): class PlantViewSet(viewsets.ModelViewSet):
""" """
@ -20,3 +30,48 @@ class PlantViewSet(viewsets.ModelViewSet):
return queryset return queryset
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.")

View file

@ -21,6 +21,9 @@ from right_tree.api import views
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'plants', views.PlantViewSet) 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 = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),