Private
Public Access
1
0

Completed views.py

This commit is contained in:
Sander Roosendaal
2017-01-14 15:59:50 +01:00
parent 220bc531dd
commit 737ac5fd3f
2 changed files with 73 additions and 249 deletions

View File

@@ -226,7 +226,6 @@ urlpatterns = [
if settings.DEBUG:
urlpatterns += [
url(r'^workout/uploadd/$',views.workout_upload_view_debug),
url(r'^testreverse/$',views.test_reverse_view),
url(r'^c2listug/$',views.c2listdebug_view),
]

View File

@@ -2678,7 +2678,7 @@ def workout_comparison_view(request,id1=0,id2=0,xparam='distance',yparam='spm'):
'yparam':yparam,
})
# Updated version of comparison pliot
# Updated version of comparison plot
def workout_comparison_view2(request,id1=0,id2=0,xparam='distance',
yparam='spm',plottype='line'):
promember=0
@@ -2945,6 +2945,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
'the_div':div,
'mayedit':mayedit})
# the page where you can chose where to export this workout
@login_required()
def workout_export_view(request,id=0, message="", successmessage=""):
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
@@ -2968,6 +2969,7 @@ def workout_export_view(request,id=0, message="", successmessage=""):
'successmessage':successmessage,
})
# The basic edit page
@login_required()
def workout_edit_view(request,id=0,message="",successmessage=""):
request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE
@@ -3008,7 +3010,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
row.boattype = boattype
row.save()
# change data in csv file
# startdatetime = dateutil.parser.parse("{}, {}".format(date,starttime))
r = rdata(row.csvfilename)
if r == 0:
return HttpResponse("Error: CSV Data File Not Found")
@@ -3124,6 +3126,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
})
return HttpResponseRedirect(url)
# Create the chart image with wind corrected pace (OTW)
@user_passes_test(promember,login_url="/",redirect_field_name=None)
def workout_add_otw_powerplot_view(request,id):
w = Workout.objects.get(id=id)
@@ -3168,7 +3171,7 @@ def workout_add_otw_powerplot_view(request,id):
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the Heart rate zone pie chart
@login_required()
def workout_add_piechart_view(request,id):
w = Workout.objects.get(id=id)
@@ -3212,7 +3215,8 @@ def workout_add_piechart_view(request,id):
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the Power zone pie chart
@login_required()
def workout_add_power_piechart_view(request,id):
w = Workout.objects.get(id=id)
@@ -3248,15 +3252,14 @@ def workout_add_power_piechart_view(request,id):
res = queue.enqueue(handle_makeplot,f1,w.csvfilename,
w.name,hrpwrdata,plotnr,imagename)
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
# filename=fullpathimagename)
i = GraphImage(workout=w,creationdatetime=timezone.now(),
filename=fullpathimagename)
i.save()
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the time based summary chart
@login_required()
def workout_add_timeplot_view(request,id):
w = Workout.objects.get(id=id)
@@ -3301,7 +3304,7 @@ def workout_add_timeplot_view(request,id):
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the distance based summary chart
@login_required()
def workout_add_distanceplot_view(request,id):
w = Workout.objects.get(id=id)
@@ -3339,13 +3342,12 @@ def workout_add_distanceplot_view(request,id):
i = GraphImage(workout=w,creationdatetime=timezone.now(),
filename=fullpathimagename)
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
# filename=fullpathimagename)
i.save()
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the advanced parameters distance overview chart
@user_passes_test(promember,login_url="/",redirect_field_name=None)
def workout_add_distanceplot2_view(request,id):
w = Workout.objects.get(id=id)
@@ -3382,14 +3384,14 @@ def workout_add_distanceplot2_view(request,id):
i = GraphImage(workout=w,creationdatetime=timezone.now(),
filename=fullpathimagename)
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
# filename=fullpathimagename)
i.save()
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# Create the advanced parameters time based overview chart
@user_passes_test(promember,login_url="/",redirect_field_name=None)
def workout_add_timeplot2_view(request,id):
w = Workout.objects.get(id=id)
@@ -3426,13 +3428,13 @@ def workout_add_timeplot2_view(request,id):
i = GraphImage(workout=w,creationdatetime=timezone.now(),
filename=fullpathimagename)
# i = GraphImage(workout=w,creationdatetime=datetime.datetime.now(),
# filename=fullpathimagename)
i.save()
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
# The page where you select which Strava workout to import
@login_required()
def workout_stravaimport_view(request,message=""):
res = stravastuff.get_strava_workout_list(request.user)
@@ -3461,6 +3463,7 @@ def workout_stravaimport_view(request,message=""):
return HttpResponse(res)
# The page where you select which SportTracks page to import
@login_required()
def workout_sporttracksimport_view(request,message=""):
res = sporttracksstuff.get_sporttracks_workout_list(request.user)
@@ -3499,6 +3502,7 @@ def workout_sporttracksimport_view(request,message=""):
return HttpResponse(res)
# List of workouts on Concept2 logbook. This view only used for debugging
@login_required()
def c2listdebug_view(request,message=""):
try:
@@ -3541,7 +3545,7 @@ def c2listdebug_view(request,message=""):
{'workouts':workouts,
'message':message})
# List of workouts available on Concept2 logbook - for import
@login_required()
def workout_c2import_view(request,message=""):
try:
@@ -3582,6 +3586,7 @@ def workout_c2import_view(request,message=""):
{'workouts':workouts,
'message':message})
# Import a workout from Strava
@login_required()
def workout_getstravaworkout_view(request,stravaid):
res = stravastuff.get_strava_workout(request.user,stravaid)
@@ -3595,6 +3600,7 @@ def workout_getstravaworkout_view(request,stravaid):
url = "/rowers/workout/"+str(id)+"/edit"
return HttpResponseRedirect(url)
# Imports a workout from SportTracks
@login_required()
def workout_getsporttracksworkout_view(request,sporttracksid):
res = sporttracksstuff.get_sporttracks_workout(request.user,sporttracksid)
@@ -3607,6 +3613,7 @@ def workout_getsporttracksworkout_view(request,sporttracksid):
url = "/rowers/workout/"+str(id)+"/edit"
return HttpResponseRedirect(url)
# Imports a workout from Concept2
@login_required()
def workout_getc2workout_view(request,c2id):
try:
@@ -3624,6 +3631,7 @@ def workout_getc2workout_view(request,c2id):
if 'intervals' in data['workout']:
splitdata = data['workout']['intervals']
# Check if workout has stroke data, and get the stroke data
if data['stroke_data']:
res2 = c2stuff.get_c2_workout_strokes(request.user,c2id)
else:
@@ -3634,12 +3642,16 @@ def workout_getc2workout_view(request,c2id):
})
return HttpResponseRedirect(url)
# We have stroke data
if res2.status_code == 200:
strokedata = pd.DataFrame.from_dict(res2.json()['data'])
# create the workout
id = add_workout_from_strokedata(request.user,c2id,data,strokedata,
source='c2')
w = Workout.objects.get(id=id)
w.uploadedtoc2=c2id
# If we have split data, update the stroke data so they
# match exactly (some users are anal about this)
if splitdata:
try:
w.summary,sa,results = c2stuff.summaryfromsplitdata(splitdata,data,w.csvfilename)
@@ -3655,7 +3667,7 @@ def workout_getc2workout_view(request,c2id):
w.save()
from rowingdata.trainingparser import getlist
# set stroke data
# set stroke data in CSV file
if sa:
values = getlist(sa)
units = getlist(sa,sel='unit')
@@ -3697,7 +3709,7 @@ def workout_getc2workout_view(request,c2id):
})
return HttpResponseRedirect(url)
# This is the main view for processing uploaded files
@login_required()
def workout_upload_view(request,message=""):
if request.method == 'POST':
@@ -3707,7 +3719,6 @@ def workout_upload_view(request,message=""):
f = request.FILES['file']
res = handle_uploaded_file(f)
t = form.cleaned_data['title']
# fileformat = form.cleaned_data['fileformat']
workouttype = form.cleaned_data['workouttype']
notes = form.cleaned_data['notes']
@@ -3719,15 +3730,18 @@ def workout_upload_view(request,message=""):
f1 = res[0] # file name
f2 = res[1] # file name incl media directory
# new
# get file type (ErgData, NK, BoatCoach, etc
fileformat = get_file_type(f2)
if len(fileformat)==3 and fileformat[0]=='zip':
f_to_be_deleted = f2
with zipfile.ZipFile(f2) as z:
# for now, we're getting only the first file
# from the NK zip file (issue #69 on bitbucket)
f2 = z.extract(z.namelist()[0],path='media/')
fileformat = fileformat[2]
os.remove(f_to_be_deleted)
# Some people try to upload Concept2 logbook summaries
if fileformat == 'c2log':
message = "This C2 logbook summary does not contain stroke data. Please download the Export Stroke Data file from the workout details on the C2 logbook."
url = reverse(workout_upload_view,
@@ -3735,13 +3749,18 @@ def workout_upload_view(request,message=""):
response = HttpResponseRedirect(url)
return response
# Some people try to upload RowPro summary logs
if fileformat == 'rowprolog':
message = "This RowPro logbook summary does not contain stroke data. Please use the Stroke Data CSV file for the individual workout in your log."
url = reverse(workout_upload_view,
args=[str(message)])
response = HttpResponseRedirect(url)
return response
# Sometimes people try an unsupported file type.
# Send an email to info@rowsandall.com with the file attached
# for me to check if it is a bug, or a new file type
# worth supporting
if fileformat == 'unknown':
message = "We couldn't recognize the file type"
url = reverse(workout_upload_view,
@@ -3758,7 +3777,8 @@ def workout_upload_view(request,message=""):
return response
summary = ''
# handle non-Painsled
# handle non-Painsled by converting it to painsled
# compatible CSV
try:
if (fileformat != 'csv'):
# handle RowPro:
@@ -3811,23 +3831,25 @@ def workout_upload_view(request,message=""):
# handle FIT
if (fileformat == 'fit'):
row = FITParser(f2)
# The FIT files have nice lap/split summaries
# so we make use of it
s = fitsummarydata(f2)
s.setsummary()
summary = s.summarytext
# Save the Painsled compatible CSV file and delete
# the uploaded file
f_to_be_deleted = f2
# should delete file
f2 = f2[:-4]+'o.csv'
row.write_csv(f2,gzip=True)
#os.remove(f2)
try:
os.remove(f_to_be_deleted)
except:
os.remove(f_to_be_deleted+'.gz')
# make workout and put in database
# make Workout object and put in database
r = Rower.objects.get(user=request.user)
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
@@ -3870,7 +3892,6 @@ def workout_upload_view(request,message=""):
if workouttype == 'rower' or workouttype == 'dynamic' or workouttype == 'slides':
try:
row.erg_recalculatepower()
# row.spm_fromtimestamps()
row.write_csv(f2,gzip=True)
except:
pass
@@ -3917,8 +3938,11 @@ def workout_upload_view(request,message=""):
startdatetime=workoutstartdatetime)
w.save()
# put stroke data in database
res = dataprep.dataprep(row.df,id=w.id,bands=True,barchart=True,otwpower=True,empower=True)
res = dataprep.dataprep(row.df,id=w.id,
bands=True,barchart=True,
otwpower=True,empower=True)
# Make Plot
if (make_plot):
@@ -3946,8 +3970,6 @@ def workout_upload_view(request,message=""):
plotnr = plotnr+3
# res = handle_makeplot.delay(f1,f2,t,
# hrpwrdata,plotnr,imagename)
if settings.DEBUG:
res = handle_makeplot.delay(f1,f2,t,
hrpwrdata,plotnr,
@@ -3961,9 +3983,6 @@ def workout_upload_view(request,message=""):
i = GraphImage(workout=w,
creationdatetime=timezone.now(),
filename=fullpathimagename)
# i = GraphImage(workout=w,
# creationdatetime=datetime.datetime.now(),
# filename=fullpathimagename)
i.save()
# upload to C2
@@ -4037,216 +4056,8 @@ def workout_upload_view(request,message=""):
'message':message})
@login_required()
def workout_upload_view_debug(request,message=""):
if request.method == 'POST':
form = DocumentsForm(request.POST,request.FILES)
optionsform = UploadOptionsForm(request.POST)
if form.is_valid():
f = request.FILES['file']
res = handle_uploaded_file(f)
t = form.cleaned_data['title']
fileformat = form.cleaned_data['fileformat']
workouttype = form.cleaned_data['workouttype']
notes = form.cleaned_data['notes']
make_plot = request.POST.getlist('make_plot')
plottype = request.POST['plottype']
upload_to_c2 = request.POST.getlist('upload_to_C2')
f1 = res[0] # file name
f2 = res[1] # file name incl media directory
# handle non-Painsled
if (fileformat != 'csv'):
# handle RowPro:
if (fileformat == 'rp'):
row = RowProParser(f2)
# handle TCX
if (fileformat == 'tcx'):
row = TCXParser(f2)
# handle TCX no HR
if (fileformat == 'tcxnohr'):
row = TCXParserNoHR(f2)
# handle ErgData
if (fileformat == 'ergdata'):
row = ErgDataParser(f2)
# handle BoatCoach
if (fileformat == 'boatcoach'):
row = BoatCoachParser(f2)
# handle painsled desktop
if (fileformat == 'painsleddesktop'):
row = painsledDesktopParser(f2)
# handle speed coach
if (fileformat == 'speedcoach'):
row = speedcoachParser(f2)
# handle ErgStick
if (fileformat == 'ergstick'):
row = ErgStickParser(f2)
f_to_be_deleted = f2
# should delete file
f2 = f2[:-4]+'o.csv'
row.write_csv(f2,gzip=True)
try:
os.remove(f_to_be_deleted)
except:
os.remove(f_to_be_deleted+'.gz')
# remove uncompressed
# make workout and put in database
r = Rower.objects.get(user=request.user)
rr = rrower(hrmax=r.max,hrut2=r.ut2,
hrut1=r.ut1,hrat=r.at,
hrtr=r.tr,hran=r.an,ftp=r.ftp)
row = rdata(f2,rower=rr)
if row == 0:
return HttpResponse("Error: CSV Data File Not Found")
row.write_csv(f2,gzip=True)
averagehr = row.df[' HRCur (bpm)'].mean()
maxhr = row.df[' HRCur (bpm)'].max()
totaldist = row.df['cum_dist'].max()
totaltime = row.df['TimeStamp (sec)'].max()-row.df['TimeStamp (sec)'].min()
totaltime = totaltime+row.df.ix[0,' ElapsedTime (sec)']
hours = int(totaltime/3600.)
minutes = int((totaltime - 3600.*hours)/60.)
seconds = int(totaltime - 3600.*hours - 60.*minutes)
tenths = int(10*(totaltime - 3600.*hours - 60.*minutes - seconds))
summary = row.summary()
summary += '\n'
summary += row.intervalstats()
duration = "%s:%s:%s.%s" % (hours,minutes,seconds,tenths)
workoutdate = row.rowdatetime.strftime('%Y-%m-%d')
workoutstarttime = row.rowdatetime.strftime('%H:%M:%S')
# check for duplicate start times
r = Rower.objects.get(user=request.user)
ws = Workout.objects.filter(starttime=workoutstarttime,
user=r)
if (len(ws) != 0):
print "Warning: This workout probably already exists in the database"
w = Workout(user=r,name=t,date=workoutdate,
workouttype=workouttype,
duration=duration,distance=totaldist,
weightcategory=r.weightcategory,
starttime=workoutstarttime,
csvfilename=f2,notes=notes,summary=summary,
averagehr=averagehr,maxhr=maxhr)
w.save()
# Make Plot
if (make_plot):
imagename = f1[:-4]+'.png'
fullpathimagename = 'static/plots/'+imagename
u = request.user
hrpwrdata = {
'hrmax':r.max,
'hrut2':r.ut2,
'hrut1':r.ut1,
'hrat':r.at,
'hrtr':r.tr,
'hran':r.an,
}
# make plot - asynchronous task
plotnrs = {
'timeplot':1,
'distanceplot':2,
'pieplot':3,
}
plotnr = plotnrs[plottype]
if (workouttype=='water'):
plotnr = plotnr+3
# res = handle_makeplot.delay(f1,f2,t,
# hrpwrdata,plotnr,imagename)
if settings.DEBUG:
res = handle_makeplot.delay(f1,f2,t,
hrpwrdata,plotnr,
imagename)
else:
res = queue.enqueue(handle_makeplot,f1,f2,
t,hrpwrdata,
plotnr,imagename)
i = GraphImage(workout=w,
creationdatetime=timezone.now(),
filename=fullpathimagename)
i.save()
# upload to C2
if (upload_to_c2):
try:
thetoken = c2_open(request.user)
except C2NoTokenError:
return HttpResponseRedirect("/rowers/me/c2authorize/")
try:
response = c2stuff.workout_c2_upload(request.user,w)
if (response.status_code != 201):
if settings.DEBUG:
return HttpResponse(response)
else:
message = "C2 upload failed"
url = reverse(workout_edit_view,
kwargs={
'message':message,
'id':str(w.id),
})
return HttpResponseRedirect(url)
except:
message = "C2 upload failed"
url = reverse(workout_edit_view,
kwargs={
'message':message,
'id':str(w.id),
})
return HttpResponseRedirect(url)
# redirect to workout edit page
url = "/rowers/workout/"+str(w.id)+"/edit"
return HttpResponseRedirect(url)
else:
response = render(request,
'document_form.html',
{'form':form,
'optionsform': optionsform,
'message':message})
return response
else:
form = DocumentsForm()
optionsform = UploadOptionsForm()
return render(request, 'document_form.html',
{'form':form,
'optionsform': optionsform,
'message':message})
# Ask the user if he really wants to delete the workout
@login_required()
def workout_delete_confirm_view(request, id=0):
try:
@@ -4261,6 +4072,7 @@ def workout_delete_confirm_view(request, id=0):
except Workout.DoesNotExist:
return HttpResponseNotFound("Workout doesn't exist")
# Really deleting the workout
@login_required()
def workout_delete_view(request,id=0):
try:
@@ -4280,7 +4092,7 @@ def workout_delete_view(request,id=0):
except Workout.DoesNotExist:
return HttpResponseNotFound("Workout doesn't exist")
# Ask the user to confirm that he wants to delete a chart
@login_required()
def graph_delete_confirm_view(request, id=0):
try:
@@ -4296,6 +4108,7 @@ def graph_delete_confirm_view(request, id=0):
except Workout.DoesNotExist:
return HttpResponseNotFound("Workout doesn't exist")
# Really deleting the chart
@login_required()
def graph_delete_view(request,id=0):
try:
@@ -4317,7 +4130,7 @@ def graph_delete_view(request,id=0):
return HttpResponse("Graph Image doesn't exist")
# A page with all the recent graphs (searchable on workout name)
@login_required()
def graphs_view(request):
try:
@@ -4344,7 +4157,7 @@ def graphs_view(request):
except Rower.DoesNotExist:
return HttpResponse("User has no rower instance")
# Show the chart (png image)
def graph_show_view(request,id):
try:
g = GraphImage.objects.get(id=id)
@@ -4359,6 +4172,7 @@ def graph_show_view(request,id):
except GraphImage.DoesNotExist:
return HttpResponse("This graph doesn't exist")
# Restore original stroke data and summary
@login_required()
def workout_summary_restore_view(request,id,message="",successmessage=""):
try:
@@ -4406,7 +4220,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""):
return HttpResponseRedirect(url)
# Edit the splits/summary
@login_required()
def workout_summary_edit_view(request,id,message="",successmessage=""
):
@@ -4594,7 +4408,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
'savebutton':savebutton,
})
# Page where user can manage his favorite charts
@user_passes_test(promember,login_url="/rowers/me/edit",redirect_field_name=None)
def rower_favoritecharts_view(request):
message = ''
@@ -4658,6 +4472,8 @@ def rower_favoritecharts_view(request):
return render(request,'favoritecharts.html',context)
# Page where user can set his details
# Add email address to form so user can change his email address
@login_required()
def rower_edit_view(request,message=""):
if request.method == 'POST' and "ut2" in request.POST:
@@ -4740,6 +4556,9 @@ def rower_edit_view(request,message=""):
except Rower.DoesNotExist:
return HttpResponse("This user doesn't exist")
# Revoke an app that you granted access through the API.
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@login_required()
def rower_revokeapp_view(request,id=0):
tokens = AccessToken.objects.filter(user=request.user,application=id)
@@ -4761,18 +4580,21 @@ def rower_revokeapp_view(request,id=0):
})
# Utility to get stroke data in a JSON response
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
# Creates unix time stamp from a datetime object
def totimestamp(dt, epoch=datetime.datetime(1970,1,1,tzinfo=tz('UTC'))):
td = dt - epoch
# return td.total_seconds()
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
# Check if a column of a dataframe has the required (aantal)
# number of elements. Also checks if the column is a numerical type
# Replaces any faulty columns with zeros
def trydf(df,aantal,column):
try:
s = df[column]
@@ -4785,6 +4607,7 @@ def trydf(df,aantal,column):
return s
# Stroke data form to test API upload
@login_required()
def strokedataform(request,id=0):
if request.method == 'GET':
@@ -4803,7 +4626,8 @@ def strokedataform(request,id=0):
'id':id,
})
# Process the POSTed stroke data according to the API definition
# Return the GET stroke data according to the API definition
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
@@ -4827,6 +4651,7 @@ def strokedatajson(request,id):
if request.method == 'GET':
# currently only returns a subset.
columns = ['spm','time','hr','pace','power','distance']
datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
return JSONResponse(datadf)