[#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 .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
@ -61,12 +61,17 @@ class LINZPropertyViewSet(viewsets.ViewSet):
def list(self, request):
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)
serializer = AddressSerializer(address_data)
return Response(serializer.data)
else:
return HttpResponseBadRequest("No coordinate given.")
return HttpResponseBadRequest("No parameters given.")
class AuckCHCHRegionInformation(viewsets.ViewSet):
""" Filtered viewset defining if coordinate falls inside auckland and chch regions.

View file

@ -1,7 +1,9 @@
import json
import os
import re
import requests
from urllib.parse import urlencode
from unicodedata import normalize
from django.contrib.gis.geos import Point, GEOSGeometry
from django.conf import settings
@ -12,6 +14,10 @@ PROPERTY_TILE_LAYER = "layer-50804"
PROPERTY_INFO_LAYER = "layer-53353"
search_num = re.compile(r'((?<!\S)\d+)')
search_str = re.compile(r'((?<!\S)[a-zA-Z\-]+)')
class WFSError(Exception):
pass
@ -85,3 +91,44 @@ def get_address_from_coordinates(coordinates):
if propertyPolygon is not None:
prop_geom = GEOSGeometry(json.dumps(propertyPolygon['geometry']))
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
]