summaryrefslogtreecommitdiff
path: root/app/locations/models.py
diff options
context:
space:
mode:
authorluxagraf <sng@luxagraf.net>2019-12-29 18:19:26 -0500
committerluxagraf <sng@luxagraf.net>2019-12-29 18:19:26 -0500
commit09abece4982e8dceabe1dd8d678639205a4a6208 (patch)
tree8b27a3369ae6f61e7f0ed52d64e261b556157f00 /app/locations/models.py
parente47d256783c9d466ab34b0632c70ac767011f91e (diff)
Added new GPX tracking model and Walk to locations
Diffstat (limited to 'app/locations/models.py')
-rw-r--r--app/locations/models.py122
1 files changed, 121 insertions, 1 deletions
diff --git a/app/locations/models.py b/app/locations/models.py
index f160b1f..e9eb047 100644
--- a/app/locations/models.py
+++ b/app/locations/models.py
@@ -1,9 +1,12 @@
import json
import requests
+import datetime
from django import forms
+from django.dispatch import receiver
+from django.db.models.signals import post_save
from django.urls import reverse
from django.apps import apps
-from django.contrib.gis.geos import GEOSGeometry, fromstr, MultiPolygon
+from django.contrib.gis.geos import GEOSGeometry, fromstr, MultiPolygon, Point, LineString, MultiLineString
from django.contrib.gis.db import models
from django.contrib.sitemaps import Sitemap
from django.utils.safestring import mark_safe
@@ -175,6 +178,7 @@ class Location(models.Model):
self.description_html = markdown_to_html(self.description)
super(Location, self).save()
+
class Route(models.Model):
"""Model to hold routes for longer trips"""
name = models.CharField(max_length=200)
@@ -380,3 +384,119 @@ def get_bounds(lat, lon):
if poly.geom_type == 'Polygon':
poly = MultiPolygon(fromstr(data[0]['geotext']))
return poly
+
+
+def get_gpx_folder(instance, filename):
+ return "images/gpx/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename)
+
+
+class GPXFile(models.Model):
+ title = models.CharField(max_length=300)
+ raw_data = models.TextField(blank=True)
+ gpx_file = models.FileField(upload_to=get_gpx_folder, blank=True)
+
+ class Meta:
+ ordering = ('title',)
+
+ def __str__(self):
+ return str(self.title)
+
+ def save(self, *args, **kwargs):
+ created = self.pk is None
+ print(self.gpx_file.path)
+ super(GPXFile, self).save(*args, **kwargs)
+
+
+class GPXPoint(models.Model):
+ name = models.CharField("Name", max_length=50, blank=True)
+ description = models.CharField("Description", max_length=250, blank=True)
+ gpx_file = models.ForeignKey(GPXFile, on_delete=models.CASCADE)
+ point = models.PointField()
+
+ def __str__(self):
+ return str(self.name)
+
+class GPXTrack(models.Model):
+ track = models.MultiLineStringField()
+ gpx_file = models.ForeignKey(GPXFile, on_delete=models.CASCADE)
+
+
+@receiver(post_save, sender=GPXFile)
+def post_save_events(sender, update_fields, created, instance, **kwargs):
+ #if created:
+ with open(instance.gpx_file.path, 'r') as f:
+ instance.raw_data = f.read()
+ parse_gpx(instance, instance.raw_data)
+ post_save.disconnect(post_save_events, sender=GPXFile)
+ instance.save()
+ post_save.connect(post_save_events, sender=GPXFile)
+
+
+import gpxpy
+import gpxpy.gpx
+
+def parse_gpx(gpx_obj, gpx_data):
+ gpx = gpxpy.parse(gpx_data)
+ if gpx.waypoints:
+ for waypoint in gpx.waypoints:
+ new_waypoint = GPXPoint()
+ if waypoint.name:
+ new_waypoint.name = waypoint.name
+ else:
+ new_waypoint.name = 'unknown'
+ new_waypoint.point = Point(waypoint.longitude, waypoint.latitude)
+ new_waypoint.gpx_file = gpx_obj
+ new_waypoint.save()
+
+ if gpx.tracks:
+ for track in gpx.tracks:
+ print("track name:" +str(track.name))
+ new_track = GPXTrack()
+ for segment in track.segments:
+
+ track_list_of_points = []
+ for point in segment.points:
+
+ point_in_segment = Point(point.longitude, point.latitude)
+ track_list_of_points.append(point_in_segment.coords)
+
+ new_track_segment = LineString(track_list_of_points)
+
+ new_track.track = MultiLineString(new_track_segment)
+ new_track.gpx_file = gpx_obj
+ new_track.save()
+
+
+class Walk(models.Model):
+ title = models.CharField(max_length=300)
+ slug = models.SlugField()
+ body_markdown = models.TextField()
+ body_html = models.TextField(blank=True)
+ date_walked = models.DateField(default=timezone.now)
+ point = models.PointField(blank=True)
+ location = models.ForeignKey(Location, on_delete=models.CASCADE, blank=True, null=True)
+ gpx_file = models.ForeignKey(GPXFile, null=True, on_delete=models.SET_NULL)
+ RATINGS = (
+ ('1', "1 Star"),
+ ('2', "2 Stars"),
+ ('3', "3 Stars"),
+ ('4', "4 Stars"),
+ ('5', "5 Stars"),
+ )
+ rating = models.CharField(max_length=1, choices=RATINGS, null=True, blank=True)
+ distance = models.DecimalField(max_digits=3, decimal_places=1, null=True)
+
+ def __str_(self):
+ return self.title
+
+ def save(self, *args, **kwargs):
+ created = self.pk is None
+ if not created:
+ md = render_images(self.body_markdown)
+ self.body_html = markdown_to_html(md)
+ try:
+ self.location = Location.objects.filter(geometry__contains=self.point).get()
+ except Location.DoesNotExist:
+ raise forms.ValidationError("There is no location associated with that point, add it: %sadmin/locations/location/add/" % (settings.BASE_URL))
+ super(Walk, self).save(*args, **kwargs)
+