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:
parent
283431085f
commit
45196f9823
11 changed files with 129 additions and 6 deletions
|
@ -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'),
|
||||
|
|
|
@ -11,3 +11,4 @@ psycopg2-binary
|
|||
Pillow
|
||||
whitenoise
|
||||
django-resized
|
||||
django-geojson
|
|
@ -4,7 +4,7 @@
|
|||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[1.9221462784913, 48.457599361977],
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"ISOCODE": "MX-CMX"
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[-99.111241, 19.561498],
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"AWATER": 23736382213
|
||||
},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[-94.0430515276176, 32.6930299766656],
|
||||
|
|
|
@ -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')
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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),
|
||||
),
|
||||
]
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue