diff options
author | luxagraf <sng@luxagraf.net> | 2019-12-29 18:19:26 -0500 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2019-12-29 18:19:26 -0500 |
commit | 09abece4982e8dceabe1dd8d678639205a4a6208 (patch) | |
tree | 8b27a3369ae6f61e7f0ed52d64e261b556157f00 /app/locations/models.py | |
parent | e47d256783c9d466ab34b0632c70ac767011f91e (diff) |
Added new GPX tracking model and Walk to locations
Diffstat (limited to 'app/locations/models.py')
-rw-r--r-- | app/locations/models.py | 122 |
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) + |