1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-22 14:29:36 +02:00

GEO Point checker!

This commit is contained in:
Sean Morley 2024-08-23 13:56:27 -04:00
parent 283431085f
commit 45196f9823
11 changed files with 129 additions and 6 deletions

View file

@ -58,6 +58,7 @@ INSTALLED_APPS = (
'adventures',
'worldtravel',
'users',
'django.contrib.gis',
)
@ -100,7 +101,7 @@ SIMPLE_JWT = {
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'NAME': getenv('PGDATABASE'),
'USER': getenv('PGUSER'),
'PASSWORD': getenv('PGPASSWORD'),

View file

@ -11,3 +11,4 @@ psycopg2-binary
Pillow
whitenoise
django-resized
django-geojson

View file

@ -4,7 +4,7 @@
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"type": "MultiPolygon",
"coordinates": [
[
[1.9221462784913, 48.457599361977],

View file

@ -10,7 +10,7 @@
"ISOCODE": "MX-CMX"
},
"geometry": {
"type": "Polygon",
"type": "MultiPolygon",
"coordinates": [
[
[-99.111241, 19.561498],

View file

@ -16,7 +16,7 @@
"AWATER": 23736382213
},
"geometry": {
"type": "Polygon",
"type": "MultiPolygon",
"coordinates": [
[
[-94.0430515276176, 32.6930299766656],

View file

@ -4,11 +4,66 @@ from django.contrib.auth import get_user_model
import requests
from worldtravel.models import Country, Region
from django.db import transaction
from django.contrib.gis.geos import GEOSGeometry, Polygon, MultiPolygon
from django.contrib.gis.geos.error import GEOSException
import json
from django.conf import settings
media_root = settings.MEDIA_ROOT
def setGeometry(region_code):
# Assuming the file name is the country code (e.g., 'AU.json' for Australia)
country_code = region_code.split('-')[0]
json_file = os.path.join('static/data', f'{country_code.lower()}.json')
if not os.path.exists(json_file):
print(f'File {country_code}.json does not exist')
return None
try:
with open(json_file, 'r') as f:
geojson_data = json.load(f)
except json.JSONDecodeError as e:
print(f"Invalid JSON in file for {country_code}: {e}")
return None
if 'type' not in geojson_data or geojson_data['type'] != 'FeatureCollection':
print(f"Invalid GeoJSON structure for {country_code}: missing or incorrect 'type'")
return None
if 'features' not in geojson_data or not geojson_data['features']:
print(f"Invalid GeoJSON structure for {country_code}: missing or empty 'features'")
return None
for feature in geojson_data['features']:
try:
properties = feature.get('properties', {})
isocode = properties.get('ISOCODE')
if isocode == region_code:
geometry = feature['geometry']
geos_geom = GEOSGeometry(json.dumps(geometry))
if isinstance(geos_geom, Polygon):
Region.objects.filter(id=region_code).update(geometry=MultiPolygon([geos_geom]))
print(f"Updated geometry for region {region_code}")
return MultiPolygon([geos_geom])
elif isinstance(geos_geom, MultiPolygon):
Region.objects.filter(id=region_code).update(geometry=geos_geom)
print(f"Updated geometry for region {region_code}")
return geos_geom
else:
print(f"Unexpected geometry type for region {region_code}: {type(geos_geom)}")
return None
except (KeyError, ValueError, GEOSException) as e:
print(f"Error processing region {region_code}: {e}")
print(f"No matching region found for {region_code}")
return None
def saveCountryFlag(country_code):
flags_dir = os.path.join(media_root, 'flags')
@ -616,7 +671,9 @@ class Command(BaseCommand):
)
if created:
self.stdout.write(f'Inserted {name} into worldtravel regions')
setGeometry(id)
else:
setGeometry(id)
self.stdout.write(f'Updated {name} in worldtravel regions')
def insert_countries(self, countries):
@ -627,6 +684,7 @@ class Command(BaseCommand):
)
if created:
saveCountryFlag(country_code)
self.stdout.write(f'Inserted {name} into worldtravel countries')
else:
saveCountryFlag(country_code)
@ -641,5 +699,7 @@ class Command(BaseCommand):
)
if created:
self.stdout.write(f'Inserted {name} into worldtravel regions')
setGeometry(id)
else:
setGeometry(id)
self.stdout.write(f'{name} already exists in worldtravel regions')

View file

@ -0,0 +1,19 @@
# Generated by Django 5.0.8 on 2024-08-23 17:01
import django.contrib.gis.db.models.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('worldtravel', '0003_alter_region_name_en'),
]
operations = [
migrations.AddField(
model_name='country',
name='geometry',
field=django.contrib.gis.db.models.fields.MultiPolygonField(blank=True, null=True, srid=4326),
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 5.0.8 on 2024-08-23 17:47
import django.contrib.gis.db.models.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('worldtravel', '0004_country_geometry'),
]
operations = [
migrations.RemoveField(
model_name='country',
name='geometry',
),
migrations.AddField(
model_name='region',
name='geometry',
field=django.contrib.gis.db.models.fields.MultiPolygonField(blank=True, null=True, srid=4326),
),
]

View file

@ -1,6 +1,7 @@
from django.db import models
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.contrib.gis.db import models as gis_models
User = get_user_model()
@ -35,6 +36,7 @@ class Country(models.Model):
default=AFRICA
)
class Meta:
verbose_name = "Country"
verbose_name_plural = "Countries"
@ -47,6 +49,7 @@ class Region(models.Model):
name = models.CharField(max_length=100)
name_en = models.CharField(max_length=100, blank=True, null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
geometry = gis_models.MultiPolygonField(srid=4326, null=True, blank=True)
def __str__(self):
return self.name

View file

@ -16,7 +16,7 @@ class CountrySerializer(serializers.ModelSerializer):
class Meta:
model = Country
fields = '__all__' # Serialize all fields of the Adventure model
read_only_fields = ['id', 'name', 'country_code', 'continent', 'flag_url']
read_only_fields = ['id', 'name', 'country_code', 'continent', 'flag_url', 'geometry']
class RegionSerializer(serializers.ModelSerializer):
class Meta:

View file

@ -8,7 +8,10 @@ from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
import os
import json
from django.http import JsonResponse
from django.contrib.gis.geos import Point
from django.conf import settings
from rest_framework.decorators import action
from django.contrib.staticfiles import finders
@api_view(['GET'])
@ -34,6 +37,19 @@ class CountryViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = CountrySerializer
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['get'])
def check_point_in_region(self, request):
lat = float(request.query_params.get('lat'))
lon = float(request.query_params.get('lon'))
point = Point(lon, lat, srid=4326)
region = Region.objects.filter(geometry__contains=point).first()
if region:
return Response({'in_region': True, 'region_name': region.name})
else:
return Response({'in_region': False})
class RegionViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Region.objects.all()
serializer_class = RegionSerializer