[#40] Address search #89

Merged
mattn merged 6 commits from matt/40-batch into main 2023-02-10 14:22:49 +13:00
2 changed files with 55 additions and 3 deletions
Showing only changes of commit ff197cc1a8 - Show all commits

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
]