courses functionality
This commit is contained in:
@@ -9,7 +9,6 @@ from django.db import IntegrityError
|
|||||||
import uuid
|
import uuid
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from utils import myqueue
|
|
||||||
|
|
||||||
from matplotlib import path
|
from matplotlib import path
|
||||||
import xml.etree.ElementTree as et
|
import xml.etree.ElementTree as et
|
||||||
@@ -18,10 +17,6 @@ import pandas as pd
|
|||||||
|
|
||||||
ns = {'opengis': 'http://www.opengis.net/kml/2.2'}
|
ns = {'opengis': 'http://www.opengis.net/kml/2.2'}
|
||||||
|
|
||||||
import django_rq
|
|
||||||
queue = django_rq.get_queue('default')
|
|
||||||
queuelow = django_rq.get_queue('low')
|
|
||||||
queuehigh = django_rq.get_queue('low')
|
|
||||||
|
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
Rower, Workout,
|
Rower, Workout,
|
||||||
@@ -128,10 +123,27 @@ def time_in_polygon(df,polygon,maxmin='max'):
|
|||||||
|
|
||||||
return time
|
return time
|
||||||
|
|
||||||
|
def crewnerdcourse(doc):
|
||||||
|
courses = []
|
||||||
|
for course in doc:
|
||||||
|
name = course.findall('.//opengis:name',ns)[0].text
|
||||||
|
try:
|
||||||
|
description = course.findall('.//opengis:description',ns)[0].text
|
||||||
|
except IndexError:
|
||||||
|
description = ''
|
||||||
|
|
||||||
def kmltocourse(f):
|
polygonpms = course.findall('.//opengis:Placemark[opengis:Polygon]',ns)
|
||||||
doc = et.parse(f)
|
polygons = get_polygons(polygonpms)
|
||||||
polygonpms = doc.findall('.//opengis:Placemark[opengis:Polygon]',ns)
|
|
||||||
|
courses.append({
|
||||||
|
'name':name,
|
||||||
|
'description':description,
|
||||||
|
'polygons':polygons
|
||||||
|
})
|
||||||
|
|
||||||
|
return courses
|
||||||
|
|
||||||
|
def get_polygons(polygonpms):
|
||||||
polygons = []
|
polygons = []
|
||||||
for pm in polygonpms:
|
for pm in polygonpms:
|
||||||
name = pm.findall('.//opengis:name',ns)[0].text
|
name = pm.findall('.//opengis:name',ns)[0].text
|
||||||
@@ -158,6 +170,19 @@ def kmltocourse(f):
|
|||||||
|
|
||||||
return polygons
|
return polygons
|
||||||
|
|
||||||
|
|
||||||
|
def kmltocourse(f):
|
||||||
|
doc = et.parse(f)
|
||||||
|
courses = doc.findall('.//opengis:Folder[opengis:Placemark]',ns)
|
||||||
|
|
||||||
|
if courses:
|
||||||
|
return crewnerdcourse(courses)
|
||||||
|
|
||||||
|
polygonpms = doc.findall('.//opengis:Placemark[opengis:Polygon]',ns)
|
||||||
|
|
||||||
|
return get_polygons(polygonpms)
|
||||||
|
|
||||||
|
|
||||||
from geopy.geocoders import Nominatim
|
from geopy.geocoders import Nominatim
|
||||||
geolocator = Nominatim()
|
geolocator = Nominatim()
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ from django.conf import settings
|
|||||||
|
|
||||||
from courses import (
|
from courses import (
|
||||||
course_coord_center,course_coord_maxmin,
|
course_coord_center,course_coord_maxmin,
|
||||||
|
polygon_coord_center
|
||||||
)
|
)
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
@@ -731,6 +732,20 @@ def course_map(course):
|
|||||||
|
|
||||||
polygons = GeoPolygon.objects.filter(course=course).order_by("order_in_course")
|
polygons = GeoPolygon.objects.filter(course=course).order_by("order_in_course")
|
||||||
|
|
||||||
|
plabels = ''
|
||||||
|
|
||||||
|
for p in polygons:
|
||||||
|
coords = polygon_coord_center(p)
|
||||||
|
|
||||||
|
plabels += """
|
||||||
|
var marker = L.marker([{latbegin}, {longbegin}]).addTo(mymap);
|
||||||
|
marker.bindPopup("<b>{name}</b>");
|
||||||
|
|
||||||
|
""".format(
|
||||||
|
latbegin = coords[0],
|
||||||
|
longbegin = coords[1],
|
||||||
|
name = p.name
|
||||||
|
)
|
||||||
|
|
||||||
pcoordinates = """[
|
pcoordinates = """[
|
||||||
"""
|
"""
|
||||||
@@ -818,12 +833,15 @@ def course_map(course):
|
|||||||
var platlongs = {pcoordinates}
|
var platlongs = {pcoordinates}
|
||||||
var polygons = L.polygon(platlongs, {{color:'blue'}}).addTo(mymap)
|
var polygons = L.polygon(platlongs, {{color:'blue'}}).addTo(mymap)
|
||||||
|
|
||||||
|
{plabels}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
""".format(
|
""".format(
|
||||||
latmean=latmean,
|
latmean=latmean,
|
||||||
lonmean=lonmean,
|
lonmean=lonmean,
|
||||||
scoordinates=scoordinates,
|
scoordinates=scoordinates,
|
||||||
pcoordinates=pcoordinates
|
pcoordinates=pcoordinates,
|
||||||
|
plabels = plabels
|
||||||
)
|
)
|
||||||
|
|
||||||
div = """
|
div = """
|
||||||
|
|||||||
@@ -667,7 +667,21 @@ class GeoCourse(models.Model):
|
|||||||
notes = models.CharField(blank=True,max_length=200,verbose_name='Course Notes')
|
notes = models.CharField(blank=True,max_length=200,verbose_name='Course Notes')
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
name = self.name
|
name = self.name
|
||||||
return u'{name}'.format(name=name)
|
country = self.country
|
||||||
|
|
||||||
|
return u'{country} - {name}'.format(
|
||||||
|
name=name,
|
||||||
|
country=country
|
||||||
|
)
|
||||||
|
|
||||||
|
class GeoCourseEditForm(ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = GeoCourse
|
||||||
|
fields = ['name','notes']
|
||||||
|
|
||||||
|
widgets = {
|
||||||
|
'notes': forms.Textarea,
|
||||||
|
}
|
||||||
|
|
||||||
class GeoPolygon(models.Model):
|
class GeoPolygon(models.Model):
|
||||||
name = models.CharField(max_length=150,blank=True)
|
name = models.CharField(max_length=150,blank=True)
|
||||||
|
|||||||
54
rowers/templates/course_edit_view.html
Normal file
54
rowers/templates/course_edit_view.html
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% load rowerfilters %}
|
||||||
|
{% block scripts %}
|
||||||
|
{% include "monitorjobs.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block title %}{{ course.name }} {% endblock %}
|
||||||
|
{% block og_title %}{{ course.name }} {% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="grid_12 alpha">
|
||||||
|
<div class="grid_2 alpha">
|
||||||
|
{% if nosessions %}
|
||||||
|
<a class="button small red" href="/rowers/courses/{{ course.id }}/delete">Delete</a>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="grid_2">
|
||||||
|
{% if course.manager == rower %}
|
||||||
|
<a class="button small gray" href="/rowers/courses/{{ course.id }}">View Course</a>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="grid_2">
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid_12 alpha">
|
||||||
|
|
||||||
|
<h1>{{ course.name }}</h1>
|
||||||
|
|
||||||
|
<div class="grid_6 alpha">
|
||||||
|
<form id="course_form" method="post">
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div id="formbutton" class="grid_1 prefix_4 suffix_1 alpha">
|
||||||
|
<input class="button green" type="submit" value="Submit">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="grid_6 omega">
|
||||||
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ mapscript|safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|||||||
@@ -9,21 +9,47 @@
|
|||||||
{% block og_title %}{{ course.name }} {% endblock %}
|
{% block og_title %}{{ course.name }} {% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
{% if nosessions %}
|
|
||||||
<div class="grid_2 alpha">
|
<div class="grid_2 alpha">
|
||||||
|
{% if nosessions %}
|
||||||
<a class="button small red" href="/rowers/courses/{{ course.id }}/delete">Delete</a>
|
<a class="button small red" href="/rowers/courses/{{ course.id }}/delete">Delete</a>
|
||||||
</div>
|
{% else %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="grid_2">
|
||||||
|
{% if course.manager == rower %}
|
||||||
|
<a class="button small gray" href="/rowers/courses/{{ course.id }}/edit">Edit</a>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="grid_2">
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
|
|
||||||
<h1>{{ course.name }}</h1>
|
<h1>{{ course.name }}</h1>
|
||||||
|
|
||||||
|
<div class="grid_6 alpha">
|
||||||
|
<table class="listtable shortpadded" width="100%">
|
||||||
|
<tr>
|
||||||
|
<th>Name</th><td>{{ course.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Country</th><td>{{ course.country }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Notes</th><td>{{ course.notes }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="grid_6 omega">
|
||||||
{{ mapdiv|safe }}
|
{{ mapdiv|safe }}
|
||||||
|
|
||||||
|
|
||||||
{{ mapscript|safe }}
|
{{ mapscript|safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<div class="grid_12">
|
<div class="grid_12">
|
||||||
|
|
||||||
<div id="courses_table" class="grid_8 alpha">
|
<div id="courses_table" class="grid_8 alpha">
|
||||||
<h3>Courses</h3>
|
<h1>Courses</h1>
|
||||||
|
|
||||||
{% if courses %}
|
{% if courses %}
|
||||||
<table width="100%" class="listtable shortpadded">
|
<table width="100%" class="listtable shortpadded">
|
||||||
@@ -29,17 +29,18 @@
|
|||||||
<th> Country</th>
|
<th> Country</th>
|
||||||
<th> Name</th>
|
<th> Name</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for course in courses %}
|
{% for course in courses %}
|
||||||
<td> {{ course.country }} </td>
|
<tr>
|
||||||
<td>
|
<td> {{ course.country }} </td>
|
||||||
{% if course.manager.user == user %}
|
<td>
|
||||||
<a href="/rowers/courses/{{ course.id }}/edit">{{ course.name }}</a>
|
{% if course.manager.user == user %}
|
||||||
{% else %}
|
<a href="/rowers/courses/{{ course.id }}/edit">{{ course.name }}</a>
|
||||||
<a href="/rowers/courses/{{ course.id }}">{{ course.name }}</a>
|
{% else %}
|
||||||
{% endif %}
|
<a href="/rowers/courses/{{ course.id }}">{{ course.name }}</a>
|
||||||
</td>
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@@ -49,7 +50,31 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<p> No courses found </p>
|
<p> No courses found </p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="grid_6 alpha">
|
||||||
|
<div class="grid_2 prefix_1 alpha">
|
||||||
|
<a class="button small green" href="/rowers/courses/upload">Add Courses</a>
|
||||||
|
</div>
|
||||||
|
<p> </p>
|
||||||
|
<form id="searchform" action="/rowers/list-courses/"
|
||||||
|
method="get" accept-charset="utf-8">
|
||||||
|
<div class="grid_3 prefix_1 alpha">
|
||||||
|
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search">
|
||||||
|
</div>
|
||||||
|
<div class="grid_1 omega">
|
||||||
|
<button class="button blue small" type="submit">
|
||||||
|
Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid_2 omega">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_4 omega">
|
<div class="grid_4 omega">
|
||||||
@@ -68,40 +93,52 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_4" id="about">
|
<div class="grid_4" id="about">
|
||||||
<h3>About</h3>
|
<h2>How-to</h2>
|
||||||
<p>This site is a beta site, pioneering rowing data visualization and analysis. No warranties. The site's author is
|
<p>
|
||||||
Sander Roosendaal. A Masters rower.
|
Courses allow you to mark the start & finish lines of your
|
||||||
|
test pieces and measure the time spent on the course (as opposed
|
||||||
|
to the total duration of a workout). This allows you to row and rank
|
||||||
|
marked courses.
|
||||||
|
|
||||||
|
To create a course, you use <a href="earth.google.com">Google Earth</a>
|
||||||
|
to mark the start and finish lines using polygons. The process is identical
|
||||||
|
to creating custom courses for the
|
||||||
|
<a href="http://performancephones.com/crewnerd/">CrewNerd</a>
|
||||||
|
app.
|
||||||
|
|
||||||
Read his <a href="http://blog.rowsandall.com/">blog</a>
|
|
||||||
</p>
|
</p>
|
||||||
<div style="text-align: right; padding: 2em">
|
|
||||||
<a href="http://blog.rowsandall.com/">
|
<p>CrewNerd has published a nice video tutorial of the process.
|
||||||
<img src="/static/img/sander.jpg" width="80"></a>
|
<a href="https://youtu.be/whhWFmMJbhM">Click here</a> to see the video. The part
|
||||||
</div>
|
we're interested in starts at 2:05.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In addition to start and finish areas, on rowsandall.com you can add additional
|
||||||
|
polygons to mark areas that you must pass (in that order). This allows for
|
||||||
|
courses with turns around buoys, respecting buoy lines, or respecting traffic
|
||||||
|
patterns on rivers and lakes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<ul>
|
||||||
|
<li>Open Google Earth</li>
|
||||||
|
<li>Create Start polygon</li>
|
||||||
|
<li>Optional: Create First "must row through" polygon</li>
|
||||||
|
<li>Optional: Create subsequent "must row through" polygons</li>
|
||||||
|
<li>Create Finish polygon</li>
|
||||||
|
<li>Save Place as KML file</li>
|
||||||
|
<li>Upload the file to rowsandall.com using the "Add Courses" button</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>You are allowed to have multiple courses in one KML file.
|
||||||
|
Your CrewNerd "courses.kml" file works out of the box</p>
|
||||||
|
|
||||||
|
<p>The site doesn't test for duplicate courses.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 prefix_1 alpha">
|
|
||||||
<a class="button small green" href="/rowers/courses/upload">Add Course</a>
|
|
||||||
</div>
|
|
||||||
<p> </p>
|
|
||||||
<form id="searchform" action="/rowers/list-courses/"
|
|
||||||
method="get" accept-charset="utf-8">
|
|
||||||
<div class="grid_3 prefix_1 alpha">
|
|
||||||
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search">
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega">
|
|
||||||
<button class="button blue small" type="submit">
|
|
||||||
Search
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -57,7 +57,11 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="grid_2 omega">
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
|
|||||||
@@ -53,6 +53,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="grid_2 omega">
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
<div id="right" class="grid_6 alpha">
|
<div id="right" class="grid_6 alpha">
|
||||||
|
|||||||
@@ -56,7 +56,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="grid_2 omega">
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
</div>
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
{% if plannedsessions %}
|
{% if plannedsessions %}
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -22,6 +22,13 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid_2">
|
||||||
|
{% if plannedsession.sessiontype == 'coursetest' %}
|
||||||
|
<a class="button small gray" href="/rowers/list-courses">Courses</a>
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_12 alpha">
|
<div class="grid_12 alpha">
|
||||||
<div id="left" class="grid_6 alpha">
|
<div id="left" class="grid_6 alpha">
|
||||||
@@ -128,6 +135,16 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="grid_12 alpha">
|
||||||
|
<div id="left" class="grid_6 alpha">
|
||||||
|
{% if coursescript %}
|
||||||
|
<h1>Course</h1>
|
||||||
|
{{ coursediv|safe }}
|
||||||
|
|
||||||
|
{{ coursescript|safe }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -489,6 +489,7 @@ urlpatterns = [
|
|||||||
url(r'^courses/(?P<id>\d+)/edit$',views.course_edit_view,
|
url(r'^courses/(?P<id>\d+)/edit$',views.course_edit_view,
|
||||||
name='course_edit_view'),
|
name='course_edit_view'),
|
||||||
url(r'^courses/(?P<id>\d+)/delete$',views.course_delete_view),
|
url(r'^courses/(?P<id>\d+)/delete$',views.course_delete_view),
|
||||||
|
url(r'^courses/(?P<id>\d+)$',views.course_view),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ from rowers.models import (
|
|||||||
Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
|
Team,TeamForm,TeamInviteForm,TeamInvite,TeamRequest,
|
||||||
WorkoutComment,WorkoutCommentForm,RowerExportForm,
|
WorkoutComment,WorkoutCommentForm,RowerExportForm,
|
||||||
CalcAgePerformance,PowerTimeFitnessMetric,PlannedSessionForm,
|
CalcAgePerformance,PowerTimeFitnessMetric,PlannedSessionForm,
|
||||||
PlannedSessionFormSmall,
|
PlannedSessionFormSmall,GeoCourseEditForm,
|
||||||
)
|
)
|
||||||
from rowers.models import (
|
from rowers.models import (
|
||||||
FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement,BasePlannedSessionFormSet
|
FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement,BasePlannedSessionFormSet
|
||||||
@@ -6051,9 +6051,20 @@ def boxplot_view(request,userid=0,
|
|||||||
def courses_view(request):
|
def courses_view(request):
|
||||||
r = getrower(request.user)
|
r = getrower(request.user)
|
||||||
|
|
||||||
courses = GeoCourse.objects.all().order_by("country")
|
courses = GeoCourse.objects.all().order_by("country","name")
|
||||||
|
|
||||||
# add search processing
|
# add search processing
|
||||||
|
query = request.GET.get('q')
|
||||||
|
if query:
|
||||||
|
query_list = query.split()
|
||||||
|
courses = GeoCourse.objects.filter(
|
||||||
|
reduce(operator.and_,
|
||||||
|
(Q(name__icontains=q) for q in query_list)) |
|
||||||
|
reduce(operator.and_,
|
||||||
|
(Q(country__icontains=q) for q in query_list)) |
|
||||||
|
reduce(operator.and_,
|
||||||
|
(Q(notes__icontains=q) for q in query_list))
|
||||||
|
)
|
||||||
|
|
||||||
return render(request,'list_courses.html',
|
return render(request,'list_courses.html',
|
||||||
{'courses':courses,
|
{'courses':courses,
|
||||||
@@ -8445,6 +8456,39 @@ def course_edit_view(request,id=0):
|
|||||||
ps = PlannedSession.objects.filter(course=course)
|
ps = PlannedSession.objects.filter(course=course)
|
||||||
nosessions = len(ps) == 0
|
nosessions = len(ps) == 0
|
||||||
|
|
||||||
|
script,div = course_map(course)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = GeoCourseEditForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
name = form.cleaned_data['name']
|
||||||
|
notes = form.cleaned_data['notes']
|
||||||
|
|
||||||
|
course.name = name
|
||||||
|
course.notes = notes
|
||||||
|
course.save()
|
||||||
|
|
||||||
|
form = GeoCourseEditForm(instance=course)
|
||||||
|
|
||||||
|
return render(request, 'course_edit_view.html',
|
||||||
|
{
|
||||||
|
'course':course,
|
||||||
|
'mapscript':script,
|
||||||
|
'mapdiv':div,
|
||||||
|
'nosessions':nosessions,
|
||||||
|
'rower':r,
|
||||||
|
'form':form,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def course_view(request,id=0):
|
||||||
|
try:
|
||||||
|
course = GeoCourse.objects.get(id=id)
|
||||||
|
except GeoCourse.DoesNotExist:
|
||||||
|
return Http404("Course doesn't exist")
|
||||||
|
|
||||||
|
r = getrower(request.user)
|
||||||
|
|
||||||
script,div = course_map(course)
|
script,div = course_map(course)
|
||||||
|
|
||||||
@@ -8453,7 +8497,8 @@ def course_edit_view(request,id=0):
|
|||||||
'course':course,
|
'course':course,
|
||||||
'mapscript':script,
|
'mapscript':script,
|
||||||
'mapdiv':div,
|
'mapdiv':div,
|
||||||
'nosessions':nosessions,
|
'nosessions':False,
|
||||||
|
'rower':r,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -8945,9 +8990,15 @@ def course_upload_view(request):
|
|||||||
if f is not None:
|
if f is not None:
|
||||||
filename,path_and_filename = handle_uploaded_file(f)
|
filename,path_and_filename = handle_uploaded_file(f)
|
||||||
|
|
||||||
polygons = courses.kmltocourse(path_and_filename)
|
cs = courses.kmltocourse(path_and_filename)
|
||||||
|
|
||||||
|
for course in cs:
|
||||||
|
cname = name+' - '+course['name']
|
||||||
|
cnotes = notes+'\n\n'+course['description']
|
||||||
|
polygons = course['polygons']
|
||||||
|
|
||||||
|
course = courses.createcourse(r,cname,polygons,notes=cnotes)
|
||||||
|
|
||||||
course = courses.createcourse(r,name,polygons,notes=notes)
|
|
||||||
os.remove(path_and_filename)
|
os.remove(path_and_filename)
|
||||||
|
|
||||||
url = reverse(courses_view)
|
url = reverse(courses_view)
|
||||||
@@ -12571,6 +12622,12 @@ def plannedsession_view(request,id=0,rowerid=0,
|
|||||||
raise Http404("Planned Session does not exist")
|
raise Http404("Planned Session does not exist")
|
||||||
|
|
||||||
|
|
||||||
|
if ps.course:
|
||||||
|
coursescript,coursediv = course_map(ps.course)
|
||||||
|
else:
|
||||||
|
coursescript = ''
|
||||||
|
coursediv = ''
|
||||||
|
|
||||||
if ps.manager != request.user and r not in ps.rower.all():
|
if ps.manager != request.user and r not in ps.rower.all():
|
||||||
raise PermissionDenied("You do not have access to this session")
|
raise PermissionDenied("You do not have access to this session")
|
||||||
|
|
||||||
@@ -12623,6 +12680,8 @@ def plannedsession_view(request,id=0,rowerid=0,
|
|||||||
'plannedsession':ps,
|
'plannedsession':ps,
|
||||||
'timeperiod':timeperiod,
|
'timeperiod':timeperiod,
|
||||||
'ranking':ranking,
|
'ranking':ranking,
|
||||||
|
'coursescript': coursescript,
|
||||||
|
'coursediv': coursediv
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user