feat: use location proxy to make Location search interface more intuitive
This commit is contained in:
parent
8e2c0e857c
commit
399ecf73ad
@ -11,6 +11,7 @@ from django.contrib.auth.models import AbstractUser
|
||||
|
||||
from .tools import misc, geo
|
||||
from notfellchen.settings import MEDIA_URL
|
||||
from .tools.geo import LocationProxy
|
||||
|
||||
|
||||
class Language(models.Model):
|
||||
@ -45,26 +46,30 @@ class Location(models.Model):
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.latitude:.5}, {self.longitude:.5})"
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
return (self.latitude, self.longitude)
|
||||
|
||||
@property
|
||||
def str_hr(self):
|
||||
return f"{self.name.split(',')[0]}"
|
||||
|
||||
@staticmethod
|
||||
def get_location_from_string(location_string):
|
||||
geo_api = geo.GeoAPI()
|
||||
geojson = geo_api.get_geojson_for_query(location_string)
|
||||
if geojson is None:
|
||||
try:
|
||||
proxy = LocationProxy(location_string)
|
||||
except ValueError:
|
||||
return None
|
||||
result = geojson[0]
|
||||
if "name" in result:
|
||||
name = result["name"]
|
||||
else:
|
||||
name = result["display_name"]
|
||||
location = Location.get_location_from_proxy(proxy)
|
||||
return location
|
||||
|
||||
@staticmethod
|
||||
def get_location_from_proxy(proxy):
|
||||
location = Location.objects.create(
|
||||
place_id=result["place_id"],
|
||||
latitude=result["lat"],
|
||||
longitude=result["lon"],
|
||||
name=name,
|
||||
place_id=proxy.place_id,
|
||||
latitude=proxy.latitude,
|
||||
longitude=proxy.longitude,
|
||||
name=proxy.name,
|
||||
)
|
||||
return location
|
||||
|
||||
|
@ -65,7 +65,8 @@ class GeoAPI:
|
||||
def get_coordinates_from_query(self, location_string):
|
||||
try:
|
||||
result = \
|
||||
self.requests.get(self.api_url, {"q": location_string, "format": "jsonv2"}, headers=self.headers).json()[0]
|
||||
self.requests.get(self.api_url, {"q": location_string, "format": "jsonv2"},
|
||||
headers=self.headers).json()[0]
|
||||
except IndexError:
|
||||
return None
|
||||
return result["lat"], result["lon"]
|
||||
@ -89,6 +90,36 @@ class GeoAPI:
|
||||
return result
|
||||
|
||||
|
||||
class LocationProxy:
|
||||
"""
|
||||
Location proxy is used as a precursor to the location model without the need to create unnecessary database objects
|
||||
"""
|
||||
|
||||
def __init__(self, location_string):
|
||||
"""
|
||||
Creates the location proxy from the location string
|
||||
"""
|
||||
self.geo_api = GeoAPI()
|
||||
geojson = self.geo_api.get_geojson_for_query(location_string)
|
||||
if geojson is None:
|
||||
raise ValueError
|
||||
result = geojson[0]
|
||||
if "name" in result:
|
||||
self.name = result["name"]
|
||||
else:
|
||||
self.name = result["display_name"]
|
||||
self.place_id = result["place_id"]
|
||||
self.latitude = result["lat"]
|
||||
self.longitude = result["lon"]
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.place_id == other.place_id
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
return (self.latitude, self.longitude)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
geo = GeoAPI(debug=False)
|
||||
print(geo.get_coordinates_from_query("12101"))
|
||||
|
@ -1,7 +1,7 @@
|
||||
import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .geo import GeoAPI
|
||||
from .geo import GeoAPI, LocationProxy
|
||||
from ..forms import AdoptionNoticeSearchForm
|
||||
from ..models import SearchSubscription, AdoptionNotice, AdoptionNoticeNotification, SexChoicesWithAll, Location
|
||||
|
||||
@ -21,16 +21,20 @@ def notify_search_subscribers(adoption_notice: AdoptionNotice):
|
||||
|
||||
|
||||
class Search:
|
||||
def __init__(self):
|
||||
def __init__(self, request=None, search_subscription=None):
|
||||
self.sex = None
|
||||
self.area_search = None
|
||||
self.max_distance = None
|
||||
self.location_string = None
|
||||
self.search_position = None
|
||||
self.location = None
|
||||
self.place_not_found = False # Indicates that a location was given but could not be geocoded
|
||||
self.search_form = None
|
||||
|
||||
if request:
|
||||
self.search_from_request(request)
|
||||
elif search_subscription:
|
||||
self.search_from_search_subscription(search_subscription)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return f"Search: {self.sex=}, {self.location=}, {self.search_position=}, {self.area_search=}, {self.max_distance=}"
|
||||
|
||||
@ -57,7 +61,7 @@ class Search:
|
||||
# make sure it's an area search and the place is found to check location
|
||||
if self.area_search and not self.place_not_found:
|
||||
# If adoption notice is in not in search distance, return false
|
||||
if not adoption_notice.in_distance(self.search_position, self.max_distance):
|
||||
if not adoption_notice.in_distance(self.location.position, self.max_distance):
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -82,9 +86,9 @@ class Search:
|
||||
self.location_string = self.search_form.cleaned_data["location_string"]
|
||||
self.max_distance = int(self.search_form.cleaned_data["max_distance"])
|
||||
|
||||
geo_api = GeoAPI()
|
||||
self.search_position = geo_api.get_coordinates_from_query(self.location_string)
|
||||
if self.search_position is None:
|
||||
try:
|
||||
self.location = LocationProxy(self.location_string)
|
||||
except ValueError:
|
||||
self.place_not_found = True
|
||||
else:
|
||||
self.search_form = AdoptionNoticeSearchForm()
|
||||
@ -94,7 +98,6 @@ class Search:
|
||||
search = Search()
|
||||
search.sex = search_subscription.sex
|
||||
search.location = search_subscription.location
|
||||
search.search_position = (search_subscription.location.latitude, search_subscription.location.longitude)
|
||||
search.area_search = True
|
||||
search.max_distance = search_subscription.max_distance
|
||||
|
||||
@ -104,7 +107,8 @@ class Search:
|
||||
|
||||
def subscribe(self, user):
|
||||
logging.info(f"{user} subscribed to search")
|
||||
self._locate()
|
||||
if isinstance(self.location, LocationProxy):
|
||||
self.location = Location.get_location_from_proxy(self.location)
|
||||
SearchSubscription.objects.create(owner=user,
|
||||
location=self.location,
|
||||
sex=self.sex,
|
||||
@ -115,7 +119,6 @@ class Search:
|
||||
Returns true if a user is already subscribed to a search with these parameters
|
||||
"""
|
||||
user_subscriptions = SearchSubscription.objects.filter(owner=user)
|
||||
self._locate()
|
||||
for subscription in user_subscriptions:
|
||||
if self == subscription:
|
||||
return True
|
||||
|
Loading…
x
Reference in New Issue
Block a user