From 25bfcb17fddbaf41165a22dd09aba49369a7ef7f Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 28 Feb 2024 15:36:12 +0100
Subject: [PATCH] exporting courses.kml
---
rowers/courses.py | 134 +++++++++++++++++++----------
rowers/templates/list_courses.html | 54 ++++++------
rowers/urls.py | 1 +
rowers/views/apiviews.py | 24 +++++-
rowers/views/racesviews.py | 21 ++++-
rowers/views/statements.py | 2 +-
6 files changed, 165 insertions(+), 71 deletions(-)
diff --git a/rowers/courses.py b/rowers/courses.py
index 2104ea8f..faf675d2 100644
--- a/rowers/courses.py
+++ b/rowers/courses.py
@@ -227,57 +227,22 @@ def crewnerdify(polygons):
return polygons
-def coursetokml(course,cn=False):
- top = Element('kml')
- for prefix, uri in xmlns_uris_dict.items():
- if prefix != '':
- top.attrib['xmlns:' + prefix] = uri
- else:
- top.attrib['xmlns'] = uri
+def removewhitespace(s):
+ regels = s.split('\n')
+ regels = [regel for regel in regels if regel.strip()]
+ return "\n".join(regels)
- document = SubElement(top, 'Document')
- name = SubElement(document, 'name')
- name.text = 'courses'
- opendoc = SubElement(document,'open')
- opendoc.text = '1'
- style = SubElement(document,'Style', id="default")
- linestyle = SubElement(style, 'LineStyle')
- linestylecolor = SubElement(linestyle, 'color')
- linestylecolor.text = "ff00ffff"
- polystyle = SubElement(style, 'PolyStyle')
- polystylecolor = SubElement(polystyle, 'color')
- polystylecolor.text = "ff7fffff"
-
- stylemap = SubElement(document, 'StyleMap', id="default0")
- pair1 = SubElement(stylemap, 'Pair')
- pair1key = SubElement(pair1, 'key')
- pair1key.text = "normal"
- pair1styleurl = SubElement(pair1, 'styleUrl')
- pair1styleurl.text = "#default"
- pair2 = SubElement(stylemap, 'Pair')
- pair2key = SubElement(pair2, 'key')
- pair2key.text = "highlight"
- pair2styleurl = SubElement(pair2, 'styleUrl')
- pair2styleurl.text = "#hl"
-
- stylehl = SubElement(document, 'Style', id="hl")
- iconstyle = SubElement(stylehl, 'IconStyle')
- scale = SubElement(iconstyle, 'scale')
- scale.text = "1.2"
- linestyle = SubElement(stylehl, 'LineStyle')
- linestylecolor = SubElement(linestyle, 'color')
- linestylecolor.text = "ff00ffff"
- polystyle = SubElement(stylehl, 'PolyStyle')
- polystylecolor = SubElement(polystyle, 'color')
- polystylecolor.text = "ff7fffff"
-
+def getcoursefolder(course, document, cn=False):
folder2 = SubElement(document, 'Folder')
coursename = SubElement(folder2, 'name')
coursename.text = course.name
openst = SubElement(folder2, 'open')
openst.text = '1'
coursedescription = SubElement(folder2, 'description')
- coursedescription.text = "Rowsandall.com\n" + course.notes
+ if len(removewhitespace(course.notes)):
+ coursedescription.text = "Rowsandall.com\n" + removewhitespace(course.notes)
+ else:
+ coursedescription.text = "Rowsandall.com " + course.name
polygons = GeoPolygon.objects.filter(
course=course).order_by("order_in_course")
@@ -310,6 +275,87 @@ def coursetokml(course,cn=False):
lat=points[0].latitude,
lon=points[0].longitude,
)
+ return folder2
+
+def getstyle(document, id):
+ style = SubElement(document,'Style', id=id)
+ iconstyle = SubElement(style, 'IconStyle')
+ scale = SubElement(iconstyle, 'scale')
+ scale.text = "1.2"
+ linestyle = SubElement(style, 'LineStyle')
+ linestylecolor = SubElement(linestyle, 'color')
+ linestylecolor.text = "ff00ffff"
+ polystyle = SubElement(style, 'PolyStyle')
+ polystylecolor = SubElement(polystyle, 'color')
+ polystylecolor.text = "ff7fffff"
+
+ return style
+
+def getstylemap(document, id):
+ stylemap = SubElement(document, 'StyleMap', id=id)
+ pair1 = SubElement(stylemap, 'Pair')
+ pair1key = SubElement(pair1, 'key')
+ pair1key.text = "normal"
+ pair1styleurl = SubElement(pair1, 'styleUrl')
+ pair1styleurl.text = "#default"
+ pair2 = SubElement(stylemap, 'Pair')
+ pair2key = SubElement(pair2, 'key')
+ pair2key.text = "highlight"
+ pair2styleurl = SubElement(pair2, 'styleUrl')
+ pair2styleurl.text = "#hl"
+
+ return stylemap
+
+def coursestokml(courseids, cn=False):
+ courses = GeoCourse.objects.filter(id__in=courseids)
+ top = Element('kml')
+ for prefix, uri in xmlns_uris_dict.items():
+ if prefix != '':
+ top.attrib['xmlns:' + prefix] = uri
+ else:
+ top.attrib['xmlns'] = uri
+
+ document = SubElement(top, 'Document')
+ name = SubElement(document, 'name')
+ name.text = 'courses'
+
+ opendoc = SubElement(document,'open')
+ opendoc.text = '1'
+
+ style = getstyle(document, "default")
+
+ stylemap = getstylemap(document, 'default0')
+
+ stylehl = getstyle(document, "hl")
+
+ for course in courses:
+ coursefolder = getcoursefolder(course, document, cn=cn)
+
+ return prettify(top)
+
+def coursetokml(course,cn=False):
+ top = Element('kml')
+ for prefix, uri in xmlns_uris_dict.items():
+ if prefix != '':
+ top.attrib['xmlns:' + prefix] = uri
+ else:
+ top.attrib['xmlns'] = uri
+
+ document = SubElement(top, 'Document')
+ name = SubElement(document, 'name')
+ name.text = 'courses'
+
+ opendoc = SubElement(document,'open')
+ opendoc.text = '1'
+
+ style = getstyle(document, "default")
+
+ stylemap = getstylemap(document, 'default0')
+
+ stylehl = getstyle(document, "hl")
+
+ coursefolder = getcoursefolder(course, document, cn=cn)
+
return prettify(top)
diff --git a/rowers/templates/list_courses.html b/rowers/templates/list_courses.html
index 3f37a654..a70edd17 100644
--- a/rowers/templates/list_courses.html
+++ b/rowers/templates/list_courses.html
@@ -23,30 +23,36 @@
{% if courses %}
-
-
-
- | Country |
- Name |
- Distance |
-
-
-
- {% for course in courses %}
-
- | {{ course.country }} |
-
- {{ course.name }}
- |
-
- {{ course.distance }} m
- |
-
-
-
- {% endfor %}
-
-
+
{% else %}
No courses found
diff --git a/rowers/urls.py b/rowers/urls.py
index 0ef84538..30326a73 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -253,6 +253,7 @@ urlpatterns = [
name='strokedata_tcx'),
re_path(r'^api/courses/$', views.course_list, name='course_list'),
re_path(r'^api/courses/(?P\d+)/$', views.get_crewnerd_kml, name='get_crewnerd_kml'),
+ re_path(r'^api/courses/kml/$', views.get_crewnerd_multiple, name='get_crewnerd_multiple'),
re_path(r'^500v/$', views.error500_view, name='error500_view'),
re_path(r'^500q/$', views.servererror_view, name='servererror_view'),
path('502/', TemplateView.as_view(template_name='502.html'), name='502'),
diff --git a/rowers/views/apiviews.py b/rowers/views/apiviews.py
index 8827de99..1604c497 100644
--- a/rowers/views/apiviews.py
+++ b/rowers/views/apiviews.py
@@ -1,7 +1,7 @@
from rowers.views.statements import *
from rowers.tasks import handle_calctrimp
from rowers.opaque import encoder
-from rowers.courses import coursetokml
+from rowers.courses import coursetokml, coursestokml
from xml.etree import ElementTree as ET
import arrow
@@ -252,6 +252,7 @@ Optional, not for CN
- Update one or more new courses from KML
"""
@api_view(["GET"])
+@permission_classes([AllowAny])
def course_list(request):
if request.method != 'GET':
dologging('apilog.log','{m} request to KML endpoint'.format(m=request.method))
@@ -304,6 +305,7 @@ def course_list(request):
return JsonResponse(response_dict, content_type='application/json; charset=utf8')
@api_view(["GET"])
+@permission_classes([AllowAny])
def get_crewnerd_kml(request,id=0):
if request.method != 'GET':
dologging('apilog.log','{m} request to CrewNerd KML endpoint'.format(m=request.method))
@@ -318,6 +320,26 @@ def get_crewnerd_kml(request,id=0):
return HttpResponse(kml)
+#@csrf_exempt
+@api_view(["GET"])
+@permission_classes([AllowAny])
+def get_crewnerd_multiple(request):
+ if request.method != 'GET':
+ dologging('apilog.log','{m} request to CrewNerd KML endpoint'.format(m=request.method))
+ return HttpResponseNotAllowed("Method not supported")
+
+ ids = request.GET.get('id')
+ if ids is not None:
+ tdict = dict(request.GET.lists())
+ ids = [int(id) for id in tdict['id']]
+ else:
+ gcs = GeoCourse.objects.all()
+ ids = [c.id for c in gcs]
+
+ kml = coursestokml(ids, cn=True)
+
+ return HttpResponse(kml)
+
# Stroke data views
@csrf_exempt
diff --git a/rowers/views/racesviews.py b/rowers/views/racesviews.py
index e3526de1..ac7b6852 100644
--- a/rowers/views/racesviews.py
+++ b/rowers/views/racesviews.py
@@ -7,7 +7,7 @@ from django.contrib.gis.geoip2 import GeoIP2
from django import forms
from rowers.plannedsessions import timefield_to_seconds_duration
-from rowers.courses import getnearestraces, getnearestcourses
+from rowers.courses import getnearestraces, getnearestcourses,coursetokml, coursestokml
# List Courses
@@ -16,6 +16,25 @@ def courses_view(request):
r = getrower(request.user)
g = GeoIP2()
+ if request.method == 'POST':
+ try:
+ tdict = dict(request.POST.lists())
+ ids = tdict['courseid']
+ courseids = [int(id) for id in ids]
+
+ kmlstring = coursestokml(courseids)
+ kmlfilename = 'courses.kml'
+ response = HttpResponse(kmlstring)
+ response['Content-Disposition'] = 'attachment; filename="{filename}"'.format(
+ filename=kmlfilename)
+ response['Content-Type'] = 'application/octet-stream'
+
+ return response
+
+ except KeyError:
+ pass
+
+
ip = request.META.get('HTTP_X_REAL_IP', '1.1.1.1')
try:
lat_lon = g.lat_lon(ip)
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index 4c7706e3..80006ded 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -22,7 +22,7 @@ from scipy.special import lambertw
from io import BytesIO
import rowers.plots as plots
from rowers.permissions import IsOwnerOrNot, IsCompetitorOrNot
-from rest_framework.permissions import IsAuthenticated
+from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.decorators import api_view, renderer_classes, permission_classes
from rest_framework.response import Response
from rq.job import Job