[#40] Address search backend

This commit is contained in:
Matthew Northcott 2023-02-08 14:16:07 +13:00
parent a03de013de
commit ff197cc1a8
2 changed files with 55 additions and 3 deletions

View file

@ -8,7 +8,7 @@ from right_tree.api.models import Habitat, HabitatImage, Plant, EcologicalDistri
from right_tree.api.serializers import HabitatImageSerializer, HabitatSerializer, PlantSerializer, SoilOrderSerializer, EcologicalDistrictLayerSerializer, AddressSerializer, ZoneSerializer from right_tree.api.serializers import HabitatImageSerializer, HabitatSerializer, PlantSerializer, SoilOrderSerializer, EcologicalDistrictLayerSerializer, AddressSerializer, ZoneSerializer
from .filters import * from .filters import *
from .wms_utils import get_address_from_coordinates from .wms_utils import get_address_from_coordinates, search_address
from .resource_generation_utils import create_plant_csv_file, get_plant_resource_filepath, create_planting_guide_pdf, PLANTING_GUIDE_PDF_FILENAME from .resource_generation_utils import create_plant_csv_file, get_plant_resource_filepath, create_planting_guide_pdf, PLANTING_GUIDE_PDF_FILENAME
@ -61,12 +61,17 @@ class LINZPropertyViewSet(viewsets.ViewSet):
def list(self, request): def list(self, request):
coordinates = self.request.query_params.get('coordinates') coordinates = self.request.query_params.get('coordinates')
if coordinates is not None: address = self.request.query_params.get('search')
if address is not None:
results = search_address(address)
return Response(results)
elif coordinates is not None:
address_data = get_address_from_coordinates(coordinates) address_data = get_address_from_coordinates(coordinates)
serializer = AddressSerializer(address_data) serializer = AddressSerializer(address_data)
return Response(serializer.data) return Response(serializer.data)
else: else:
return HttpResponseBadRequest("No coordinate given.") return HttpResponseBadRequest("No parameters given.")
class AuckCHCHRegionInformation(viewsets.ViewSet): class AuckCHCHRegionInformation(viewsets.ViewSet):
""" Filtered viewset defining if coordinate falls inside auckland and chch regions. """ Filtered viewset defining if coordinate falls inside auckland and chch regions.

View file

@ -1,7 +1,9 @@
import json import json
import os import os
import re
import requests import requests
from urllib.parse import urlencode from urllib.parse import urlencode
from unicodedata import normalize
from django.contrib.gis.geos import Point, GEOSGeometry from django.contrib.gis.geos import Point, GEOSGeometry
from django.conf import settings from django.conf import settings
@ -12,6 +14,10 @@ PROPERTY_TILE_LAYER = "layer-50804"
PROPERTY_INFO_LAYER = "layer-53353" PROPERTY_INFO_LAYER = "layer-53353"
search_num = re.compile(r'((?<!\S)\d+)')
search_str = re.compile(r'((?<!\S)[a-zA-Z\-]+)')
class WFSError(Exception): class WFSError(Exception):
pass pass
@ -85,3 +91,44 @@ def get_address_from_coordinates(coordinates):
if propertyPolygon is not None: if propertyPolygon is not None:
prop_geom = GEOSGeometry(json.dumps(propertyPolygon['geometry'])) prop_geom = GEOSGeometry(json.dumps(propertyPolygon['geometry']))
return get_address(prop_geom) return get_address(prop_geom)
def search_address(address):
# normalize accent characters etc.
address = normalize(
"NFKD",
address.strip().lower(),
).encode("ascii", "ignore").decode()
nums = search_num.findall(address)
strings = search_str.findall(address)
num_terms = [f"address_number = {n}" for n in nums]
string_terms = []
for s in strings:
string_terms += [
f"full_road_name_ascii ILIKE '{s}%'",
f"town_city_ascii ILIKE '{s}%'",
f"suburb_locality_ascii ILIKE '{s}%'",
]
num_expr = " OR ".join(f"({term})" for term in num_terms)
string_expr = " OR ".join(f"({term})" for term in string_terms)
cql_filter = f"({num_expr}) AND ({string_expr})"
resp = linz_wfs_getfeature(
typeNames=PROPERTY_INFO_LAYER,
cql_filter=cql_filter,
count=10,
)
features = resp.get("features", [])
return [
{
'coordinates': feature['geometry']['coordinates'],
'address': feature['properties']['full_address'],
} for feature in features
]