mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-24 15:29:36 +02:00
feat: implement background geocoding for adventure locations on save
This commit is contained in:
parent
9d69935f22
commit
4e8024051c
1 changed files with 50 additions and 39 deletions
|
@ -5,6 +5,7 @@ import uuid
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.deconstruct import deconstructible
|
from django.utils.deconstruct import deconstructible
|
||||||
from adventures.managers import AdventureManager
|
from adventures.managers import AdventureManager
|
||||||
|
import threading
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
|
@ -13,6 +14,42 @@ from worldtravel.models import City, Country, Region, VisitedCity, VisitedRegion
|
||||||
from adventures.geocoding import reverse_geocode
|
from adventures.geocoding import reverse_geocode
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
def background_geocode_and_assign(adventure_id: str):
|
||||||
|
try:
|
||||||
|
adventure = Adventure.objects.get(id=adventure_id)
|
||||||
|
if not (adventure.latitude and adventure.longitude):
|
||||||
|
return
|
||||||
|
|
||||||
|
from adventures.geocoding import reverse_geocode # or wherever you defined it
|
||||||
|
is_visited = adventure.is_visited_status()
|
||||||
|
result = reverse_geocode(adventure.latitude, adventure.longitude, adventure.user_id)
|
||||||
|
|
||||||
|
if 'region_id' in result:
|
||||||
|
region = Region.objects.filter(id=result['region_id']).first()
|
||||||
|
if region:
|
||||||
|
adventure.region = region
|
||||||
|
if is_visited:
|
||||||
|
VisitedRegion.objects.get_or_create(user_id=adventure.user_id, region=region)
|
||||||
|
|
||||||
|
if 'city_id' in result:
|
||||||
|
city = City.objects.filter(id=result['city_id']).first()
|
||||||
|
if city:
|
||||||
|
adventure.city = city
|
||||||
|
if is_visited:
|
||||||
|
VisitedCity.objects.get_or_create(user_id=adventure.user_id, city=city)
|
||||||
|
|
||||||
|
if 'country_id' in result:
|
||||||
|
country = Country.objects.filter(country_code=result['country_id']).first()
|
||||||
|
if country:
|
||||||
|
adventure.country = country
|
||||||
|
|
||||||
|
# Save updated location info
|
||||||
|
adventure.save(update_fields=["region", "city", "country"])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# Optional: log or print the error
|
||||||
|
print(f"[Adventure Geocode Thread] Error processing {adventure_id}: {e}")
|
||||||
|
|
||||||
def validate_file_extension(value):
|
def validate_file_extension(value):
|
||||||
import os
|
import os
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
@ -571,51 +608,25 @@ class Adventure(models.Model):
|
||||||
if self.user_id != self.category.user_id:
|
if self.user_id != self.category.user_id:
|
||||||
raise ValidationError('Adventures must be associated with categories owned by the same user. Category owner: ' + self.category.user_id.username + ' Adventure owner: ' + self.user_id.username)
|
raise ValidationError('Adventures must be associated with categories owned by the same user. Category owner: ' + self.category.user_id.username + ' Adventure owner: ' + self.user_id.username)
|
||||||
|
|
||||||
def save(self, force_insert: bool = False, force_update: bool = False, using: str | None = None, update_fields: Iterable[str] | None = None) -> None:
|
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
|
||||||
"""
|
|
||||||
Saves the current instance. If the instance is being inserted for the first time, it will be created in the database.
|
|
||||||
If it already exists, it will be updated.
|
|
||||||
"""
|
|
||||||
if force_insert and force_update:
|
if force_insert and force_update:
|
||||||
raise ValueError("Cannot force both insert and updating in model saving.")
|
raise ValueError("Cannot force both insert and updating in model saving.")
|
||||||
if not self.category:
|
if not self.category:
|
||||||
category, created = Category.objects.get_or_create(
|
category, _ = Category.objects.get_or_create(
|
||||||
user_id=self.user_id,
|
user_id=self.user_id,
|
||||||
name='general',
|
name='general',
|
||||||
defaults={
|
defaults={'display_name': 'General', 'icon': '🌍'}
|
||||||
'display_name': 'General',
|
|
||||||
'icon': '🌍'
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
self.category = category
|
self.category = category
|
||||||
|
|
||||||
if self.latitude and self.longitude:
|
# First save the adventure quickly
|
||||||
is_visited = self.is_visited_status()
|
result = super().save(force_insert, force_update, using, update_fields)
|
||||||
reverse_geocode_result = reverse_geocode(self.latitude, self.longitude, self.user_id)
|
|
||||||
if 'region_id' in reverse_geocode_result:
|
|
||||||
region = Region.objects.filter(id=reverse_geocode_result['region_id']).first()
|
|
||||||
if region:
|
|
||||||
self.region = region
|
|
||||||
if is_visited:
|
|
||||||
visited_region, created = VisitedRegion.objects.get_or_create(
|
|
||||||
user_id=self.user_id,
|
|
||||||
region=region
|
|
||||||
)
|
|
||||||
if 'city_id' in reverse_geocode_result:
|
|
||||||
city = City.objects.filter(id=reverse_geocode_result['city_id']).first()
|
|
||||||
if city:
|
|
||||||
self.city = city
|
|
||||||
if is_visited:
|
|
||||||
visited_city, created = VisitedCity.objects.get_or_create(
|
|
||||||
user_id=self.user_id,
|
|
||||||
city=city
|
|
||||||
)
|
|
||||||
if 'country_id' in reverse_geocode_result:
|
|
||||||
country = Country.objects.filter(country_code=reverse_geocode_result['country_id']).first()
|
|
||||||
if country:
|
|
||||||
self.country = country
|
|
||||||
|
|
||||||
return super().save(force_insert, force_update, using, update_fields)
|
# Then fire off a thread to geocode + update region/city/country
|
||||||
|
if self.latitude and self.longitude:
|
||||||
|
threading.Thread(target=background_geocode_and_assign, args=(str(self.id),)).start()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue