Merge branch 'release/dbupdate'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,31 @@ from pandas import DataFrame,Series
|
|||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
user = settings.DATABASES['default']['USER']
|
||||||
|
password = settings.DATABASES['default']['PASSWORD']
|
||||||
|
database_name = settings.DATABASES['default']['NAME']
|
||||||
|
host = settings.DATABASES['default']['HOST']
|
||||||
|
port = settings.DATABASES['default']['PORT']
|
||||||
|
|
||||||
|
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
|
||||||
|
user=user,
|
||||||
|
password=password,
|
||||||
|
database_name=database_name,
|
||||||
|
host=host,
|
||||||
|
port=port,
|
||||||
|
)
|
||||||
|
|
||||||
|
if settings.DEBUG or user=='':
|
||||||
|
# database_url = 'sqlite:///db.sqlite3'
|
||||||
|
database_url = 'sqlite:///'+database_name
|
||||||
|
|
||||||
|
engine = create_engine(database_url, echo=False)
|
||||||
|
|
||||||
from scipy.signal import savgol_filter
|
from scipy.signal import savgol_filter
|
||||||
|
|
||||||
@@ -59,6 +84,55 @@ def rdata(file,rower=rrower()):
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def delete_strokedata(id):
|
||||||
|
query = sa.text('DELETE FROM strokedata WHERE workoutid={id};'.format(
|
||||||
|
id=id,
|
||||||
|
))
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
try:
|
||||||
|
result = conn.execute(query)
|
||||||
|
except:
|
||||||
|
print "Database Locked"
|
||||||
|
|
||||||
|
def testdata(time,distance,pace,spm):
|
||||||
|
t1 = np.issubdtype(time,np.number)
|
||||||
|
t2 = np.issubdtype(distance,np.number)
|
||||||
|
t3 = np.issubdtype(pace,np.number)
|
||||||
|
t4 = np.issubdtype(spm,np.number)
|
||||||
|
|
||||||
|
return t1 and t2 and t3 and t4
|
||||||
|
|
||||||
|
def getrowdata_db(id=0):
|
||||||
|
data = read_df_sql(id)
|
||||||
|
data['pace'] = data['pace']/1.0e6
|
||||||
|
data['ergpace'] = data['ergpace']/1.0e6
|
||||||
|
data['nowindpace'] = data['nowindpace']/1.0e6
|
||||||
|
data['time'] = data['time']/1.0e6
|
||||||
|
data['x_right'] = data['x_right']/1.0e6
|
||||||
|
if data.empty:
|
||||||
|
rowdata,row = getrowdata(id=id)
|
||||||
|
if rowdata:
|
||||||
|
data = dataprep(rowdata.df,id=id,bands=True,barchart=True,otwpower=True)
|
||||||
|
else:
|
||||||
|
data = pd.DataFrame() # returning empty dataframe
|
||||||
|
else:
|
||||||
|
row = Workout.objects.get(id=id)
|
||||||
|
|
||||||
|
return data,row
|
||||||
|
|
||||||
|
def getsmallrowdata_db(columns,ids=[]):
|
||||||
|
prepmultipledata(ids)
|
||||||
|
data = read_cols_df_sql(ids,columns)
|
||||||
|
for column in columns:
|
||||||
|
if column == 'time':
|
||||||
|
data['time'] = data['time']/1.0e6
|
||||||
|
if column == 'pace':
|
||||||
|
data['pace'] = data['pace']/1.0e6
|
||||||
|
if column == 'pace':
|
||||||
|
data['pace'] = data['pace']/1.0e6
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def getrowdata(id=0):
|
def getrowdata(id=0):
|
||||||
|
|
||||||
# check if valid ID exists (workout exists)
|
# check if valid ID exists (workout exists)
|
||||||
@@ -80,6 +154,56 @@ def getrowdata(id=0):
|
|||||||
return rowdata,row
|
return rowdata,row
|
||||||
|
|
||||||
|
|
||||||
|
def prepmultipledata(ids,verbose=False):
|
||||||
|
query = sa.text('SELECT DISTINCT workoutid FROM strokedata')
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
res = conn.execute(query)
|
||||||
|
res = list(itertools.chain.from_iterable(res.fetchall()))
|
||||||
|
|
||||||
|
res = list(set(ids)-set(res))
|
||||||
|
for id in res:
|
||||||
|
rowdata,row = getrowdata(id=id)
|
||||||
|
if verbose:
|
||||||
|
print id
|
||||||
|
if rowdata:
|
||||||
|
data = dataprep(rowdata.df,id=id,bands=True,barchart=True,otwpower=True)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def read_cols_df_sql(ids,columns):
|
||||||
|
columns = list(columns)+['distance','spm']
|
||||||
|
columns = [x for x in columns if x != 'None']
|
||||||
|
columns = list(set(columns))
|
||||||
|
cls = ''
|
||||||
|
for column in columns:
|
||||||
|
cls += column+', '
|
||||||
|
cls = cls[:-2]
|
||||||
|
if len(ids) == 0:
|
||||||
|
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid=0'.format(
|
||||||
|
columns = cls,
|
||||||
|
))
|
||||||
|
elif len(ids) == 1:
|
||||||
|
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid={id}'.format(
|
||||||
|
id = ids[0],
|
||||||
|
columns = cls,
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
query = sa.text('SELECT {columns} FROM strokedata WHERE workoutid IN {ids}'.format(
|
||||||
|
columns = cls,
|
||||||
|
ids = tuple(ids),
|
||||||
|
))
|
||||||
|
|
||||||
|
df = pd.read_sql_query(query,engine)
|
||||||
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
def read_df_sql(id):
|
||||||
|
df = pd.read_sql_query(sa.text('SELECT * FROM strokedata WHERE workoutid={id}'.format(
|
||||||
|
id=id)), engine)
|
||||||
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def smalldataprep(therows,xparam,yparam1,yparam2):
|
def smalldataprep(therows,xparam,yparam1,yparam2):
|
||||||
df = pd.DataFrame()
|
df = pd.DataFrame()
|
||||||
@@ -110,8 +234,7 @@ def smalldataprep(therows,xparam,yparam1,yparam2):
|
|||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
|
def dataprep(rowdatadf,id=0,bands=False,barchart=False,otwpower=False):
|
||||||
def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
|
||||||
rowdatadf.set_index([range(len(rowdatadf))],inplace=True)
|
rowdatadf.set_index([range(len(rowdatadf))],inplace=True)
|
||||||
t = rowdatadf.ix[:,'TimeStamp (sec)']
|
t = rowdatadf.ix[:,'TimeStamp (sec)']
|
||||||
t = pd.Series(t-rowdatadf.ix[0,'TimeStamp (sec)'])
|
t = pd.Series(t-rowdatadf.ix[0,'TimeStamp (sec)'])
|
||||||
@@ -127,8 +250,11 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
|||||||
power = rowdatadf.ix[:,' Power (watts)']
|
power = rowdatadf.ix[:,' Power (watts)']
|
||||||
averageforce = rowdatadf.ix[:,' AverageDriveForce (lbs)']
|
averageforce = rowdatadf.ix[:,' AverageDriveForce (lbs)']
|
||||||
drivelength = rowdatadf.ix[:,' DriveLength (meters)']
|
drivelength = rowdatadf.ix[:,' DriveLength (meters)']
|
||||||
|
try:
|
||||||
|
workoutstate = rowdatadf.ix[:,' WorkoutState']
|
||||||
|
except KeyError:
|
||||||
|
workoutstate = 0*hr
|
||||||
|
|
||||||
peakforce = rowdatadf.ix[:,' PeakDriveForce (lbs)']
|
peakforce = rowdatadf.ix[:,' PeakDriveForce (lbs)']
|
||||||
|
|
||||||
forceratio = averageforce/peakforce
|
forceratio = averageforce/peakforce
|
||||||
@@ -175,6 +301,7 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
|||||||
fpace = nicepaceformat(p2),
|
fpace = nicepaceformat(p2),
|
||||||
driveenergy=driveenergy,
|
driveenergy=driveenergy,
|
||||||
power=power,
|
power=power,
|
||||||
|
workoutstate=workoutstate,
|
||||||
averageforce=averageforce,
|
averageforce=averageforce,
|
||||||
drivelength=drivelength,
|
drivelength=drivelength,
|
||||||
peakforce=peakforce,
|
peakforce=peakforce,
|
||||||
@@ -228,5 +355,11 @@ def dataprep(rowdatadf,bands=False,barchart=False,otwpower=False):
|
|||||||
|
|
||||||
data = data.replace([-np.inf,np.inf],np.nan)
|
data = data.replace([-np.inf,np.inf],np.nan)
|
||||||
data = data.fillna(method='ffill')
|
data = data.fillna(method='ffill')
|
||||||
|
|
||||||
|
# write data if id given
|
||||||
|
if id != 0:
|
||||||
|
data['workoutid'] = id
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
data.to_sql('strokedata',engine,if_exists='append',index=False)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ class CNsummaryForm(forms.Form):
|
|||||||
class SummaryStringForm(forms.Form):
|
class SummaryStringForm(forms.Form):
|
||||||
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
intervalstring = forms.CharField(max_length=255,label='Workout Description')
|
||||||
|
|
||||||
|
class StrokeDataForm(forms.Form):
|
||||||
|
strokedata = forms.CharField(label='payload',
|
||||||
|
widget=forms.Textarea)
|
||||||
|
|
||||||
class DocumentsForm(forms.Form):
|
class DocumentsForm(forms.Form):
|
||||||
filetypechoices = (
|
filetypechoices = (
|
||||||
('csv' , 'Painsled iOS CSV'),
|
('csv' , 'Painsled iOS CSV'),
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ from rowers.dataprep import timedeltaconv
|
|||||||
def interactive_histoall(theworkouts):
|
def interactive_histoall(theworkouts):
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||||
|
|
||||||
therows = []
|
ids = [w.id for w in theworkouts]
|
||||||
for workout in theworkouts:
|
|
||||||
f1 = workout.csvfilename
|
rowdata = dataprep.getsmallrowdata_db(['power'],ids=ids)
|
||||||
rowdata = rdata(f1)
|
|
||||||
if rowdata != 0:
|
histopwr = rowdata['power'].values
|
||||||
therows.append(rowdata)
|
if len(histopwr) == 0:
|
||||||
|
return "","CSV file not found","",""
|
||||||
histopwr = histodata(therows)
|
|
||||||
# throw out nans
|
# throw out nans
|
||||||
histopwr = histopwr[~np.isinf(histopwr)]
|
histopwr = histopwr[~np.isinf(histopwr)]
|
||||||
histopwr = histopwr[histopwr > 25]
|
histopwr = histopwr[histopwr > 25]
|
||||||
@@ -496,18 +496,15 @@ def interactive_chart(id=0,promember=0):
|
|||||||
else:
|
else:
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
||||||
|
|
||||||
rowdata,row = dataprep.getrowdata(id=id)
|
|
||||||
if rowdata == 0:
|
datadf,row = dataprep.getrowdata_db(id=id)
|
||||||
|
if datadf.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
datadf = dataprep.dataprep(rowdata.df)
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
datadf
|
datadf
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
||||||
plot_width=400,
|
plot_width=400,
|
||||||
plot_height=400,
|
plot_height=400,
|
||||||
@@ -554,10 +551,10 @@ def interactive_chart(id=0,promember=0):
|
|||||||
|
|
||||||
hover.mode = 'mouse'
|
hover.mode = 'mouse'
|
||||||
|
|
||||||
plot.extra_y_ranges = {"hr": Range1d(start=100,end=200)}
|
plot.extra_y_ranges = {"hrax": Range1d(start=100,end=200)}
|
||||||
plot.line('time','hr',source=source,color="red",
|
plot.line('time','hr',source=source,color="red",
|
||||||
y_range_name="hr", legend="Heart Rate")
|
y_range_name="hrax", legend="Heart Rate")
|
||||||
plot.add_layout(LinearAxis(y_range_name="hr",axis_label="HR"),'right')
|
plot.add_layout(LinearAxis(y_range_name="hrax",axis_label="HR"),'right')
|
||||||
|
|
||||||
plot.legend.location = "bottom_right"
|
plot.legend.location = "bottom_right"
|
||||||
|
|
||||||
@@ -570,8 +567,10 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
|||||||
yparam1='power',
|
yparam1='power',
|
||||||
yparam2='spm'):
|
yparam2='spm'):
|
||||||
|
|
||||||
datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
# datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
|
||||||
|
ids = [w.id for w in theworkouts]
|
||||||
|
datadf = dataprep.getsmallrowdata_db([xparam,yparam1,yparam2],ids=ids)
|
||||||
|
|
||||||
axlabels = {
|
axlabels = {
|
||||||
'time': 'Time',
|
'time': 'Time',
|
||||||
'distance': 'Distance (m)',
|
'distance': 'Distance (m)',
|
||||||
@@ -666,6 +665,7 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
|||||||
else:
|
else:
|
||||||
datadf['yname2'] = yparam1
|
datadf['yname2'] = yparam1
|
||||||
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
source = ColumnDataSource(
|
||||||
datadf
|
datadf
|
||||||
)
|
)
|
||||||
@@ -678,7 +678,7 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
|||||||
if (promember==1):
|
if (promember==1):
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
|
||||||
else:
|
else:
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,crosshair'
|
||||||
|
|
||||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
||||||
tools=TOOLS,
|
tools=TOOLS,
|
||||||
@@ -862,384 +862,6 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
|
|||||||
return [script,div,js_resources,css_resources]
|
return [script,div,js_resources,css_resources]
|
||||||
|
|
||||||
|
|
||||||
def interactive_cum_flex_chart(theworkouts,promember=0,
|
|
||||||
xparam='spm',
|
|
||||||
yparam1='power',
|
|
||||||
yparam2='hr',
|
|
||||||
):
|
|
||||||
|
|
||||||
|
|
||||||
therows = []
|
|
||||||
for workout in theworkouts:
|
|
||||||
f1 = workout.csvfilename
|
|
||||||
rowdata = rdata(f1)
|
|
||||||
if rowdata != 0:
|
|
||||||
therows.append(rowdata.df)
|
|
||||||
|
|
||||||
datadf = pd.concat(therows)
|
|
||||||
|
|
||||||
axlabels = {
|
|
||||||
'time': 'Time',
|
|
||||||
'distance': 'Distance (m)',
|
|
||||||
'hr': 'Heart Rate (bpm)',
|
|
||||||
'spm': 'Stroke Rate (spm)',
|
|
||||||
'pace': 'Pace (/500m)',
|
|
||||||
'power': 'Power (Watt)',
|
|
||||||
'averageforce': 'Average Drive Force (lbs)',
|
|
||||||
'drivelength': 'Drive Length (m)',
|
|
||||||
'peakforce': 'Peak Drive Force (lbs)',
|
|
||||||
'forceratio': 'Average/Peak Drive Force Ratio',
|
|
||||||
'driveenergy': 'Work per Stroke (J)',
|
|
||||||
'drivespeed': 'Drive Speed (m/s)',
|
|
||||||
'None': '',
|
|
||||||
}
|
|
||||||
|
|
||||||
yparamname1 = axlabels[yparam1]
|
|
||||||
yparamname2 = axlabels[yparam2]
|
|
||||||
|
|
||||||
yaxminima = {
|
|
||||||
'hr':100,
|
|
||||||
'spm':15,
|
|
||||||
'pace': 1.0e3*210,
|
|
||||||
'power': 0,
|
|
||||||
'averageforce': 0,
|
|
||||||
'peakforce': 0,
|
|
||||||
'forceratio':0,
|
|
||||||
'drivelength':0.5,
|
|
||||||
'driveenergy': 0,
|
|
||||||
'drivespeed': 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
yaxmaxima = {
|
|
||||||
'hr':200,
|
|
||||||
'spm':45,
|
|
||||||
'pace':1.0e3*90,
|
|
||||||
'power': 600,
|
|
||||||
'averageforce':200,
|
|
||||||
'peakforce':400,
|
|
||||||
'forceratio':1,
|
|
||||||
'drivelength':2.0,
|
|
||||||
'driveenergy': 1000,
|
|
||||||
'drivespeed':4,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
datadf = dataprep.dataprep(datadf)
|
|
||||||
|
|
||||||
if yparam1 != 'pace' and yparam1 != 'time':
|
|
||||||
datadf = datadf[datadf[yparam1] > 0]
|
|
||||||
elif yparam1 == 'time':
|
|
||||||
datadf = datadf[datadf['timesecs'] > 0]
|
|
||||||
else:
|
|
||||||
datadf = datadf[datadf['pseconds']>0]
|
|
||||||
|
|
||||||
if xparam != 'time' and xparam != 'pace':
|
|
||||||
datadf = datadf[datadf[xparam] > 0]
|
|
||||||
elif xparam == 'time':
|
|
||||||
datadf = datadf[datadf['timesecs']>0]
|
|
||||||
else:
|
|
||||||
datadf = datadf[datadf['pseconds']>0]
|
|
||||||
|
|
||||||
if yparam2 != 'None':
|
|
||||||
datadf = datadf[datadf[yparam2] > 0]
|
|
||||||
|
|
||||||
# check if dataframe not empty
|
|
||||||
if datadf.empty:
|
|
||||||
return ['','<p>No non-zero data in selection</p>','','']
|
|
||||||
|
|
||||||
|
|
||||||
datadf['x1'] = datadf.ix[:,xparam]
|
|
||||||
tseconds = datadf.ix[:,'timesecs']
|
|
||||||
|
|
||||||
|
|
||||||
datadf['y1'] = datadf.ix[:,yparam1]
|
|
||||||
if yparam2 != 'None':
|
|
||||||
datadf['y2'] = datadf.ix[:,yparam2]
|
|
||||||
else:
|
|
||||||
datadf['y2'] = datadf['y1']
|
|
||||||
|
|
||||||
|
|
||||||
if xparam=='time':
|
|
||||||
xaxmax = tseconds.max()
|
|
||||||
xaxmin = tseconds.min()
|
|
||||||
xaxmax = 1.0e3*xaxmax
|
|
||||||
xaxmin = 1.0e3*xaxmin
|
|
||||||
elif xparam=='distance':
|
|
||||||
xaxmax = datadf['x1'].max()
|
|
||||||
xaxmin = datadf['x1'].min()
|
|
||||||
else:
|
|
||||||
xaxmax = yaxmaxima[xparam]
|
|
||||||
xaxmin = yaxminima[xparam]
|
|
||||||
|
|
||||||
# average values
|
|
||||||
if xparam != 'time':
|
|
||||||
x1mean = datadf['x1'].mean()
|
|
||||||
else:
|
|
||||||
x1mean = 0
|
|
||||||
|
|
||||||
y1mean = datadf['y1'].mean()
|
|
||||||
y2mean = datadf['y2'].mean()
|
|
||||||
|
|
||||||
if xparam != 'time':
|
|
||||||
xvals = pd.Series(xaxmin+np.arange(100)*(xaxmax-xaxmin)/100.)
|
|
||||||
else:
|
|
||||||
xvals = pd.Series(np.arange(100))
|
|
||||||
|
|
||||||
x_axis_type = 'linear'
|
|
||||||
y_axis_type = 'linear'
|
|
||||||
if xparam == 'time':
|
|
||||||
x_axis_type = 'datetime'
|
|
||||||
|
|
||||||
if yparam1 == 'pace':
|
|
||||||
y_axis_type = 'datetime'
|
|
||||||
y1mean = datadf.ix[:,'pseconds'].mean()
|
|
||||||
|
|
||||||
datadf['xname'] = xparam
|
|
||||||
datadf['yname1'] = yparam1
|
|
||||||
if yparam2 != 'None':
|
|
||||||
datadf['yname2'] = yparam2
|
|
||||||
else:
|
|
||||||
datadf['yname2'] = yparam1
|
|
||||||
|
|
||||||
source = ColumnDataSource(
|
|
||||||
datadf
|
|
||||||
)
|
|
||||||
|
|
||||||
source2 = ColumnDataSource(
|
|
||||||
datadf.copy()
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add hover to this comma-separated string and see what changes
|
|
||||||
if (promember==1):
|
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
|
||||||
else:
|
|
||||||
TOOLS = 'pan,box_zoom,wheel_zoom,reset,tap,hover,crosshair'
|
|
||||||
|
|
||||||
plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type,
|
|
||||||
tools=TOOLS,
|
|
||||||
toolbar_location="above",
|
|
||||||
toolbar_sticky=False)
|
|
||||||
|
|
||||||
x1means = Span(location=x1mean,dimension='height',line_color='green',
|
|
||||||
line_dash=[6,6], line_width=2)
|
|
||||||
|
|
||||||
y1means = Span(location=y1mean,dimension='width',line_color='blue',
|
|
||||||
line_dash=[6,6],line_width=2)
|
|
||||||
y2means = y1means
|
|
||||||
|
|
||||||
xlabel = Label(x=370,y=130,x_units='screen',y_units='screen',
|
|
||||||
text=xparam+": {x1mean:6.2f}".format(x1mean=x1mean),
|
|
||||||
background_fill_alpha=.7,
|
|
||||||
text_color='green',
|
|
||||||
)
|
|
||||||
|
|
||||||
if (xparam != 'time') and (xparam != 'distance'):
|
|
||||||
plot.add_layout(x1means)
|
|
||||||
plot.add_layout(xlabel)
|
|
||||||
|
|
||||||
plot.add_layout(y1means)
|
|
||||||
|
|
||||||
y1label = Label(x=370,y=100,x_units='screen',y_units='screen',
|
|
||||||
text=yparam1+": {y1mean:6.2f}".format(y1mean=y1mean),
|
|
||||||
background_fill_alpha=.7,
|
|
||||||
text_color='blue',
|
|
||||||
)
|
|
||||||
if yparam1 != 'time' and yparam1 != 'pace':
|
|
||||||
plot.add_layout(y1label)
|
|
||||||
|
|
||||||
y2label = y1label
|
|
||||||
plot.circle('x1','y1',source=source2,fill_alpha=0.3,line_color=None,
|
|
||||||
legend=yparamname1,
|
|
||||||
)
|
|
||||||
|
|
||||||
plot.xaxis.axis_label = axlabels[xparam]
|
|
||||||
plot.yaxis.axis_label = axlabels[yparam1]
|
|
||||||
|
|
||||||
|
|
||||||
yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1])
|
|
||||||
plot.y_range = yrange1
|
|
||||||
|
|
||||||
if (xparam != 'time') and (xparam != 'distance'):
|
|
||||||
xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam])
|
|
||||||
plot.x_range = xrange1
|
|
||||||
|
|
||||||
if xparam == 'time':
|
|
||||||
xrange1 = Range1d(start=xaxmin,end=xaxmax)
|
|
||||||
plot.x_range = xrange1
|
|
||||||
plot.xaxis[0].formatter = DatetimeTickFormatter(
|
|
||||||
hours = ["%H"],
|
|
||||||
minutes = ["%M"],
|
|
||||||
seconds = ["%S"],
|
|
||||||
days = ["0"],
|
|
||||||
months = [""],
|
|
||||||
years = [""]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if yparam1 == 'pace':
|
|
||||||
plot.yaxis[0].formatter = DatetimeTickFormatter(
|
|
||||||
seconds = ["%S"],
|
|
||||||
minutes = ["%M"]
|
|
||||||
)
|
|
||||||
|
|
||||||
if yparam2 != 'None':
|
|
||||||
yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2])
|
|
||||||
plot.extra_y_ranges = {"yax2": yrange2}
|
|
||||||
|
|
||||||
plot.circle('x1','y2',color="red",y_range_name="yax2",
|
|
||||||
legend=yparamname2,
|
|
||||||
source=source2,fill_alpha=0.3,line_color=None)
|
|
||||||
|
|
||||||
plot.add_layout(LinearAxis(y_range_name="yax2",
|
|
||||||
axis_label=axlabels[yparam2]),'right')
|
|
||||||
|
|
||||||
y2means = Span(location=y2mean,dimension='width',line_color='red',
|
|
||||||
line_dash=[6,6],line_width=2,y_range_name="yax2")
|
|
||||||
|
|
||||||
|
|
||||||
plot.add_layout(y2means)
|
|
||||||
y2label = Label(x=370,y=70,x_units='screen',y_units='screen',
|
|
||||||
text=yparam2+": {y2mean:6.2f}".format(y2mean=y2mean),
|
|
||||||
background_fill_alpha=.7,
|
|
||||||
text_color='red',
|
|
||||||
)
|
|
||||||
if yparam2 != 'pace' and yparam2 != 'time':
|
|
||||||
plot.add_layout(y2label)
|
|
||||||
|
|
||||||
hover = plot.select(dict(type=HoverTool))
|
|
||||||
|
|
||||||
|
|
||||||
hover.tooltips = OrderedDict([
|
|
||||||
('Time','@ftime'),
|
|
||||||
('Pace','@fpace'),
|
|
||||||
('HR','@hr{int}'),
|
|
||||||
('SPM','@spm{1.1}'),
|
|
||||||
('Power','@power{int}'),
|
|
||||||
])
|
|
||||||
|
|
||||||
hover.mode = 'mouse'
|
|
||||||
|
|
||||||
callback = CustomJS(args = dict(source=source,source2=source2,
|
|
||||||
x1means=x1means,
|
|
||||||
y1means=y1means,
|
|
||||||
y1label=y1label,
|
|
||||||
y2label=y2label,
|
|
||||||
xlabel=xlabel,
|
|
||||||
y2means=y2means), code="""
|
|
||||||
var data = source.data
|
|
||||||
var data2 = source2.data
|
|
||||||
var x1 = data['x1']
|
|
||||||
var y1 = data['y1']
|
|
||||||
var y2 = data['y2']
|
|
||||||
var spm1 = data['spm']
|
|
||||||
var time1 = data['time']
|
|
||||||
var pace1 = data['pace']
|
|
||||||
var hr1 = data['hr']
|
|
||||||
var distance1 = data['distance']
|
|
||||||
var power1 = data['power']
|
|
||||||
var xname = data['xname'][0]
|
|
||||||
var yname1 = data['yname1'][0]
|
|
||||||
var yname2 = data['yname2'][0]
|
|
||||||
|
|
||||||
var minspm = minspm.value
|
|
||||||
var maxspm = maxspm.value
|
|
||||||
var mindist = mindist.value
|
|
||||||
var maxdist = maxdist.value
|
|
||||||
var xm = 0
|
|
||||||
var ym1 = 0
|
|
||||||
var ym2 = 0
|
|
||||||
|
|
||||||
data2['x1'] = []
|
|
||||||
data2['y1'] = []
|
|
||||||
data2['y2'] = []
|
|
||||||
data2['spm'] = []
|
|
||||||
data2['time'] = []
|
|
||||||
data2['pace'] = []
|
|
||||||
data2['hr'] = []
|
|
||||||
data2['distance'] = []
|
|
||||||
data2['power'] = []
|
|
||||||
data2['x1mean'] = []
|
|
||||||
data2['y1mean'] = []
|
|
||||||
data2['y2mean'] = []
|
|
||||||
data2['xvals'] = []
|
|
||||||
data2['y1vals'] = []
|
|
||||||
data2['y2vals'] = []
|
|
||||||
|
|
||||||
for (i=0; i<x1.length; i++) {
|
|
||||||
if (spm1[i]>=minspm && spm1[i]<=maxspm) {
|
|
||||||
if (distance1[i]>=mindist && distance1[i]<=maxdist) {
|
|
||||||
data2['x1'].push(x1[i])
|
|
||||||
data2['y1'].push(y1[i])
|
|
||||||
data2['y2'].push(y2[i])
|
|
||||||
data2['spm'].push(spm1[i])
|
|
||||||
data2['time'].push(time1[i])
|
|
||||||
data2['pace'].push(pace1[i])
|
|
||||||
data2['hr'].push(hr1[i])
|
|
||||||
data2['distance'].push(distance1[i])
|
|
||||||
data2['power'].push(power1[i])
|
|
||||||
|
|
||||||
xm += x1[i]
|
|
||||||
ym1 += y1[i]
|
|
||||||
ym2 += y2[i]
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xm /= data2['x1'].length
|
|
||||||
ym1 /= data2['x1'].length
|
|
||||||
ym2 /= data2['x1'].length
|
|
||||||
|
|
||||||
data2['x1mean'] = [xm,xm]
|
|
||||||
data2['y1mean'] = [ym1,ym1]
|
|
||||||
data2['y2mean'] = [ym2,ym2]
|
|
||||||
x1means.location = xm
|
|
||||||
y1means.location = ym1
|
|
||||||
y2means.location = ym2
|
|
||||||
y1label.text = yname1+': '+ym1.toFixed(2)
|
|
||||||
y2label.text = yname2+': '+ym2.toFixed(2)
|
|
||||||
xlabel.text = xname+': '+xm.toFixed(2)
|
|
||||||
|
|
||||||
source2.trigger('change');
|
|
||||||
""")
|
|
||||||
|
|
||||||
slider_spm_min = Slider(start=15.0, end=55,value=15.0, step=.1,
|
|
||||||
title="Min SPM",callback=callback)
|
|
||||||
callback.args["minspm"] = slider_spm_min
|
|
||||||
|
|
||||||
|
|
||||||
slider_spm_max = Slider(start=15.0, end=55,value=55.0, step=.1,
|
|
||||||
title="Max SPM",callback=callback)
|
|
||||||
callback.args["maxspm"] = slider_spm_max
|
|
||||||
|
|
||||||
distmax = 100+100*int(datadf['distance'].max()/100.)
|
|
||||||
|
|
||||||
slider_dist_min = Slider(start=0,end=distmax,value=0,step=1,
|
|
||||||
title="Min Distance",callback=callback)
|
|
||||||
callback.args["mindist"] = slider_dist_min
|
|
||||||
|
|
||||||
slider_dist_max = Slider(start=0,end=distmax,value=distmax,
|
|
||||||
step=1,
|
|
||||||
title="Max Distance",callback=callback)
|
|
||||||
callback.args["maxdist"] = slider_dist_max
|
|
||||||
|
|
||||||
layout = layoutrow([layoutcolumn([slider_spm_min,
|
|
||||||
slider_spm_max,
|
|
||||||
slider_dist_min,
|
|
||||||
slider_dist_max,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
plot])
|
|
||||||
|
|
||||||
script, div = components(layout)
|
|
||||||
js_resources = INLINE.render_js()
|
|
||||||
css_resources = INLINE.render_css()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return [script,div,js_resources,css_resources]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def interactive_flex_chart2(id=0,promember=0,
|
def interactive_flex_chart2(id=0,promember=0,
|
||||||
@@ -1292,8 +914,8 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
'drivespeed':4,
|
'drivespeed':4,
|
||||||
}
|
}
|
||||||
|
|
||||||
rowdata,row = dataprep.getrowdata(id=id)
|
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||||
if rowdata == 0:
|
if rowdata.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
workoutstateswork = [1,4,5,8,9,6,7]
|
workoutstateswork = [1,4,5,8,9,6,7]
|
||||||
@@ -1302,16 +924,10 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
|
|
||||||
if workstrokesonly:
|
if workstrokesonly:
|
||||||
try:
|
try:
|
||||||
rowdata.df = rowdata.df[~rowdata.df[' WorkoutState'].isin(workoutstatesrest)]
|
rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
rowdata = dataprep.dataprep(rowdata.df)
|
|
||||||
|
|
||||||
|
|
||||||
# get user
|
|
||||||
# u = User.objects.get(id=row.user.id)
|
|
||||||
|
|
||||||
rowdata['x1'] = rowdata.ix[:,xparam]
|
rowdata['x1'] = rowdata.ix[:,xparam]
|
||||||
|
|
||||||
rowdata['y1'] = rowdata.ix[:,yparam1]
|
rowdata['y1'] = rowdata.ix[:,yparam1]
|
||||||
@@ -1634,15 +1250,10 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
|
|
||||||
def interactive_bar_chart(id=0,promember=0):
|
def interactive_bar_chart(id=0,promember=0):
|
||||||
# check if valid ID exists (workout exists)
|
# check if valid ID exists (workout exists)
|
||||||
rowdata,row = dataprep.getrowdata(id=id)
|
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||||
if rowdata == 0:
|
if rowdata.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
rowdata = dataprep.dataprep(rowdata.df,bands=True,barchart=True)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Add hover to this comma-separated string and see what changes
|
# Add hover to this comma-separated string and see what changes
|
||||||
if (promember==1):
|
if (promember==1):
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||||
@@ -1653,8 +1264,6 @@ def interactive_bar_chart(id=0,promember=0):
|
|||||||
rowdata
|
rowdata
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
plot = Figure(x_axis_type="datetime",y_axis_type="datetime",
|
||||||
toolbar_sticky=False,
|
toolbar_sticky=False,
|
||||||
plot_width=920,
|
plot_width=920,
|
||||||
@@ -1751,19 +1360,14 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
|||||||
|
|
||||||
|
|
||||||
# check if valid ID exists (workout exists)
|
# check if valid ID exists (workout exists)
|
||||||
rowdata1,row1 = dataprep.getrowdata(id=id1)
|
rowdata1,row1 = dataprep.getrowdata_db(id=id1)
|
||||||
rowdata2,row2 = dataprep.getrowdata(id=id2)
|
rowdata2,row2 = dataprep.getrowdata_db(id=id2)
|
||||||
if rowdata1 == 0:
|
if rowdata1.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
if rowdata2 == 0:
|
if rowdata2.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
rowdata1 = dataprep.dataprep(rowdata1.df)
|
|
||||||
rowdata2 = dataprep.dataprep(rowdata2.df)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
x1 = rowdata1.ix[:,xparam]
|
x1 = rowdata1.ix[:,xparam]
|
||||||
x2 = rowdata2.ix[:,xparam]
|
x2 = rowdata2.ix[:,xparam]
|
||||||
|
|
||||||
@@ -1899,12 +1503,10 @@ def interactive_comparison_chart(id1=0,id2=0,xparam='distance',yparam='spm',
|
|||||||
|
|
||||||
def interactive_otw_advanced_pace_chart(id=0,promember=0):
|
def interactive_otw_advanced_pace_chart(id=0,promember=0):
|
||||||
# check if valid ID exists (workout exists)
|
# check if valid ID exists (workout exists)
|
||||||
rowdata,row = dataprep.getrowdata(id=id)
|
rowdata,row = dataprep.getrowdata_db(id=id)
|
||||||
if rowdata == 0:
|
if rowdata.empty:
|
||||||
return "","CSV Data File Not Found"
|
return "","CSV Data File Not Found"
|
||||||
|
|
||||||
rowdata = dataprep.dataprep(rowdata.df,otwpower=True)
|
|
||||||
|
|
||||||
# Add hover to this comma-separated string and see what changes
|
# Add hover to this comma-separated string and see what changes
|
||||||
if (promember==1):
|
if (promember==1):
|
||||||
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,hover,resize,crosshair'
|
||||||
|
|||||||
@@ -9,8 +9,31 @@ from django.forms.widgets import SplitDateTimeWidget
|
|||||||
from datetimewidget.widgets import DateTimeWidget
|
from datetimewidget.widgets import DateTimeWidget
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# Create your models here.
|
from django.conf import settings
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlite3 import OperationalError
|
||||||
|
|
||||||
|
user = settings.DATABASES['default']['USER']
|
||||||
|
password = settings.DATABASES['default']['PASSWORD']
|
||||||
|
database_name = settings.DATABASES['default']['NAME']
|
||||||
|
host = settings.DATABASES['default']['HOST']
|
||||||
|
port = settings.DATABASES['default']['PORT']
|
||||||
|
|
||||||
|
database_url = 'mysql://{user}:{password}@{host}:{port}/{database_name}'.format(
|
||||||
|
user=user,
|
||||||
|
password=password,
|
||||||
|
database_name=database_name,
|
||||||
|
host=host,
|
||||||
|
port=port,
|
||||||
|
)
|
||||||
|
|
||||||
|
if settings.DEBUG or user=='':
|
||||||
|
database_url = 'sqlite:///db.sqlite3'
|
||||||
|
|
||||||
|
engine = create_engine(database_url, echo=False)
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
class Team(models.Model):
|
class Team(models.Model):
|
||||||
name = models.CharField(max_length=150)
|
name = models.CharField(max_length=150)
|
||||||
notes = models.CharField(blank=True,max_length=200)
|
notes = models.CharField(blank=True,max_length=200)
|
||||||
@@ -120,7 +143,54 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
|||||||
if os.path.isfile(instance.csvfilename):
|
if os.path.isfile(instance.csvfilename):
|
||||||
os.remove(instance.csvfilename)
|
os.remove(instance.csvfilename)
|
||||||
|
|
||||||
|
@receiver(models.signals.post_delete,sender=Workout)
|
||||||
|
def auto_delete_strokedata_on_delete(sender, instance, **kwargs):
|
||||||
|
if instance.id:
|
||||||
|
query = sa.text('DELETE FROM strokedata WHERE workoutid={id};'.format(
|
||||||
|
id=instance.id,
|
||||||
|
))
|
||||||
|
with engine.connect() as conn, conn.begin():
|
||||||
|
try:
|
||||||
|
result = conn.execute(query)
|
||||||
|
except:
|
||||||
|
print "Database Locked"
|
||||||
|
|
||||||
|
class StrokeData(models.Model):
|
||||||
|
class Meta:
|
||||||
|
db_table = 'strokedata'
|
||||||
|
|
||||||
|
workoutid = models.IntegerField(null=True)
|
||||||
|
time = models.TimeField(null=True)
|
||||||
|
timesecs = models.FloatField(null=True)
|
||||||
|
hr = models.IntegerField(null=True)
|
||||||
|
pace = models.TimeField(null=True)
|
||||||
|
workoutstate = models.IntegerField(null=True,default=1)
|
||||||
|
pseconds = models.FloatField(null=True)
|
||||||
|
spm = models.FloatField(null=True)
|
||||||
|
cumdist = models.FloatField(null=True)
|
||||||
|
ftime = models.CharField(max_length=30)
|
||||||
|
fpace = models.CharField(max_length=30)
|
||||||
|
driveenergy = models.FloatField(null=True)
|
||||||
|
power = models.FloatField(null=True)
|
||||||
|
averageforce = models.FloatField(null=True)
|
||||||
|
drivelength = models.FloatField(null=True)
|
||||||
|
peakforce = models.FloatField(null=True)
|
||||||
|
forceratio = models.FloatField(null=True)
|
||||||
|
distance = models.FloatField(null=True)
|
||||||
|
drivespeed = models.FloatField(null=True)
|
||||||
|
hr_ut2 = models.IntegerField(null=True)
|
||||||
|
hr_ut1 = models.IntegerField(null=True)
|
||||||
|
hr_at = models.IntegerField(null=True)
|
||||||
|
hr_tr = models.IntegerField(null=True)
|
||||||
|
hr_an = models.IntegerField(null=True)
|
||||||
|
hr_max = models.IntegerField(null=True)
|
||||||
|
hr_bottom = models.IntegerField(null=True)
|
||||||
|
x_right = models.FloatField(null=True)
|
||||||
|
ergpace = models.TimeField(null=True)
|
||||||
|
nowindpace = models.TimeField(null=True)
|
||||||
|
equivergpower = models.FloatField(null=True)
|
||||||
|
fergpace = models.CharField(max_length=30)
|
||||||
|
fnowindpace = models.CharField(max_length=30)
|
||||||
|
|
||||||
class GraphImage(models.Model):
|
class GraphImage(models.Model):
|
||||||
filename = models.CharField(default='',max_length=150,blank=True,null=True)
|
filename = models.CharField(default='',max_length=150,blank=True,null=True)
|
||||||
|
|||||||
280
rowers/ownapistuff.py
Normal file
280
rowers/ownapistuff.py
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
# Python
|
||||||
|
import oauth2 as oauth
|
||||||
|
import cgi
|
||||||
|
import requests
|
||||||
|
import requests.auth
|
||||||
|
import json
|
||||||
|
from django.utils import timezone
|
||||||
|
from datetime import datetime
|
||||||
|
import numpy as np
|
||||||
|
from dateutil import parser
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
from math import sin,cos,atan2,sqrt
|
||||||
|
|
||||||
|
import urllib
|
||||||
|
import c2stuff
|
||||||
|
|
||||||
|
# Django
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from django.http import HttpResponseRedirect, HttpResponse,JsonResponse
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth import authenticate, login, logout
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
# Project
|
||||||
|
# from .models import Profile
|
||||||
|
from rowingdata import rowingdata
|
||||||
|
import pandas as pd
|
||||||
|
from rowers.models import Rower,Workout
|
||||||
|
|
||||||
|
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET, SPORTTRACKS_CLIENT_SECRET, SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI
|
||||||
|
|
||||||
|
TEST_CLIENT_ID = "1"
|
||||||
|
TEST_CLIENT_SECRET = "aapnootmies"
|
||||||
|
|
||||||
|
TEST_REDIRECT_URI = "http://localhost:8000/rowers/test_callback"
|
||||||
|
|
||||||
|
def custom_exception_handler(exc,message):
|
||||||
|
|
||||||
|
response = {
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"code": str(exc),
|
||||||
|
"detail": message,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
res = HttpResponse(message)
|
||||||
|
res.status_code = 401
|
||||||
|
res.json = json.dumps(response)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def do_refresh_token(refreshtoken):
|
||||||
|
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
|
||||||
|
post_data = {"grant_type": "refresh_token",
|
||||||
|
"client_secret": TEST_CLIENT_SECRET,
|
||||||
|
"client_id":TEST_CLIENT_ID,
|
||||||
|
"refresh_token": refreshtoken,
|
||||||
|
}
|
||||||
|
headers = {'user-agent': 'sanderroosendaal',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'}
|
||||||
|
|
||||||
|
url = "http://localhost:8000/rowers/o/token"
|
||||||
|
|
||||||
|
response = requests.post(url,
|
||||||
|
data=json.dumps(post_data),
|
||||||
|
headers=headers)
|
||||||
|
|
||||||
|
token_json = response.json()
|
||||||
|
thetoken = token_json['access_token']
|
||||||
|
expires_in = token_json['expires_in']
|
||||||
|
try:
|
||||||
|
refresh_token = token_json['refresh_token']
|
||||||
|
except KeyError:
|
||||||
|
refresh_token = refreshtoken
|
||||||
|
|
||||||
|
return [thetoken,expires_in,refresh_token]
|
||||||
|
|
||||||
|
|
||||||
|
def get_token(code):
|
||||||
|
client_auth = requests.auth.HTTPBasicAuth(TEST_CLIENT_ID, TEST_CLIENT_SECRET)
|
||||||
|
post_data = {"grant_type": "authorization_code",
|
||||||
|
"code": code,
|
||||||
|
"redirect_uri": TEST_REDIRECT_URI,
|
||||||
|
"client_secret": TEST_CLIENT_SECRET,
|
||||||
|
"client_id":TEST_CLIENT_ID,
|
||||||
|
}
|
||||||
|
headers = {'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'}
|
||||||
|
|
||||||
|
url = "http://localhost:8000/rowers/o/token/"
|
||||||
|
|
||||||
|
|
||||||
|
response = requests.post(url,
|
||||||
|
data=json.dumps(post_data),
|
||||||
|
headers=headers)
|
||||||
|
|
||||||
|
print response.text
|
||||||
|
token_json = response.json()
|
||||||
|
thetoken = token_json['access_token']
|
||||||
|
expires_in = token_json['expires_in']
|
||||||
|
refresh_token = token_json['refresh_token']
|
||||||
|
|
||||||
|
return [thetoken,expires_in,refresh_token]
|
||||||
|
|
||||||
|
def make_authorization_url(request):
|
||||||
|
# Generate a random string for the state parameter
|
||||||
|
# Save it for use later to prevent xsrf attacks
|
||||||
|
from uuid import uuid4
|
||||||
|
state = str(uuid4())
|
||||||
|
|
||||||
|
params = {"client_id": TEST_CLIENT_ID,
|
||||||
|
"response_type": "code",
|
||||||
|
"redirect_uri": TEST_REDIRECT_URI,
|
||||||
|
"scope":"write",
|
||||||
|
"state":state}
|
||||||
|
|
||||||
|
|
||||||
|
import urllib
|
||||||
|
url = "http://localhost:8000/rowers/o/authorize" +urllib.urlencode(params)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|
||||||
|
def rower_ownapi_token_refresh(user):
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
res = do_refresh_token(r.ownapirefreshtoken)
|
||||||
|
access_token = res[0]
|
||||||
|
expires_in = res[1]
|
||||||
|
refresh_token = res[2]
|
||||||
|
expirydatetime = timezone.now()+timedelta(seconds=expires_in)
|
||||||
|
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
r.ownapitoken = access_token
|
||||||
|
r.tokenexpirydate = expirydatetime
|
||||||
|
r.ownapirefreshtoken = refresh_token
|
||||||
|
|
||||||
|
r.save()
|
||||||
|
return r.ownapitoken
|
||||||
|
|
||||||
|
def get_ownapi_workout_list(user):
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
if (r.ownapitoken == '') or (r.ownapitoken is None):
|
||||||
|
s = "Token doesn't exist. Need to authorize"
|
||||||
|
return custom_exception_handler(401,s)
|
||||||
|
elif (timezone.now()>r.ownapitokenexpirydate):
|
||||||
|
s = "Token expired. Needs to refresh."
|
||||||
|
return custom_exception_handler(401,s)
|
||||||
|
else:
|
||||||
|
# ready to fetch. Hurray
|
||||||
|
authorizationstring = str('Bearer ' + r.ownapitoken)
|
||||||
|
headers = {'Authorization': authorizationstring,
|
||||||
|
'user-agent': 'sanderroosendaal',
|
||||||
|
'Content-Type': 'application/json'}
|
||||||
|
url = "https://api.ownapi.mobi/api/v2/fitnessActivities"
|
||||||
|
s = requests.get(url,headers=headers)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def get_ownapi_workout(user,ownapiid):
|
||||||
|
r = Rower.objects.get(user=user)
|
||||||
|
if (r.ownapitoken == '') or (r.ownapitoken is None):
|
||||||
|
return custom_exception_handler(401,s)
|
||||||
|
s = "Token doesn't exist. Need to authorize"
|
||||||
|
elif (timezone.now()>r.ownapitokenexpirydate):
|
||||||
|
s = "Token expired. Needs to refresh."
|
||||||
|
return custom_exception_handler(401,s)
|
||||||
|
else:
|
||||||
|
# ready to fetch. Hurray
|
||||||
|
authorizationstring = str('Bearer ' + r.ownapitoken)
|
||||||
|
headers = {'Authorization': authorizationstring,
|
||||||
|
'user-agent': 'sanderroosendaal',
|
||||||
|
'Content-Type': 'application/json'}
|
||||||
|
url = "https://api.ownapi.mobi/api/v2/fitnessActivities/"+str(ownapiid)
|
||||||
|
s = requests.get(url,headers=headers)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
def createownapiworkoutdata(w):
|
||||||
|
filename = w.csvfilename
|
||||||
|
row = rowingdata(filename)
|
||||||
|
averagehr = int(row.df[' HRCur (bpm)'].mean())
|
||||||
|
maxhr = int(row.df[' HRCur (bpm)'].max())
|
||||||
|
|
||||||
|
# adding diff, trying to see if this is valid
|
||||||
|
t = row.df.ix[:,'TimeStamp (sec)'].values-10*row.df.ix[0,'TimeStamp (sec)']
|
||||||
|
t[0] = t[1]
|
||||||
|
d = row.df.ix[:,'cum_dist'].values
|
||||||
|
d[0] = d[1]
|
||||||
|
t = t.astype(int)
|
||||||
|
d = d.astype(int)
|
||||||
|
spm = row.df[' Cadence (stokes/min)'].astype(int)
|
||||||
|
spm[0] = spm[1]
|
||||||
|
hr = row.df[' HRCur (bpm)'].astype(int)
|
||||||
|
|
||||||
|
haslatlon=1
|
||||||
|
|
||||||
|
try:
|
||||||
|
lat = row.df[' latitude'].values
|
||||||
|
lon = row.df[' longitude'].values
|
||||||
|
except KeyError:
|
||||||
|
haslatlon = 0
|
||||||
|
|
||||||
|
haspower = 1
|
||||||
|
try:
|
||||||
|
power = row.df[' Power (watts)'].values
|
||||||
|
except KeyError:
|
||||||
|
haspower = 0
|
||||||
|
|
||||||
|
locdata = []
|
||||||
|
hrdata = []
|
||||||
|
spmdata = []
|
||||||
|
distancedata = []
|
||||||
|
powerdata = []
|
||||||
|
|
||||||
|
for i in range(len(t)):
|
||||||
|
hrdata.append(t[i])
|
||||||
|
hrdata.append(hr[i])
|
||||||
|
distancedata.append(t[i])
|
||||||
|
distancedata.append(d[i])
|
||||||
|
spmdata.append(t[i])
|
||||||
|
spmdata.append(spm[i])
|
||||||
|
if haslatlon:
|
||||||
|
locdata.append(t[i])
|
||||||
|
locdata.append([lat[i],lon[i]])
|
||||||
|
if haspower:
|
||||||
|
powerdata.append(t[i])
|
||||||
|
powerdata.append(power[i])
|
||||||
|
|
||||||
|
|
||||||
|
if haslatlon:
|
||||||
|
data = {
|
||||||
|
"type": "Rowing",
|
||||||
|
"name": w.name,
|
||||||
|
# "start_time": str(w.date)+"T"+str(w.starttime)+"Z",
|
||||||
|
"start_time": w.startdatetime.isoformat(),
|
||||||
|
"total_distance": int(w.distance),
|
||||||
|
"duration": int(max(t)),
|
||||||
|
"notes": w.notes,
|
||||||
|
"avg_heartrate": averagehr,
|
||||||
|
"max_heartrate": maxhr,
|
||||||
|
"location": locdata,
|
||||||
|
"distance": distancedata,
|
||||||
|
"cadence": spmdata,
|
||||||
|
"heartrate": hrdata,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
data = {
|
||||||
|
"type": "Rowing",
|
||||||
|
"name": w.name,
|
||||||
|
# "start_time": str(w.date)+"T"+str(w.starttime)+"Z",
|
||||||
|
"start_time": w.startdatetime.isoformat(),
|
||||||
|
"total_distance": int(w.distance),
|
||||||
|
"duration": int(max(t)),
|
||||||
|
"notes": w.notes,
|
||||||
|
"avg_heartrate": averagehr,
|
||||||
|
"max_heartrate": maxhr,
|
||||||
|
"distance": distancedata,
|
||||||
|
"cadence": spmdata,
|
||||||
|
"heartrate": hrdata,
|
||||||
|
}
|
||||||
|
|
||||||
|
if haspower:
|
||||||
|
data['power'] = powerdata
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def getidfromresponse(response):
|
||||||
|
t = json.loads(response.text)
|
||||||
|
uri = t['uris'][0]
|
||||||
|
id = uri[len(uri)-13:len(uri)-5]
|
||||||
|
|
||||||
|
return int(id)
|
||||||
|
|
||||||
|
|
||||||
21
rowers/permissions.py
Normal file
21
rowers/permissions.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from rest_framework import permissions
|
||||||
|
from rowers.models import Rower
|
||||||
|
|
||||||
|
class IsOwnerOrReadOnly(permissions.BasePermission):
|
||||||
|
"""
|
||||||
|
Custom permission to only allow owners of an object to edit it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
# Read permissions are allowed to any request,
|
||||||
|
# so we'll always allow GET, HEAD or OPTIONS requests.
|
||||||
|
if request.method in permissions.SAFE_METHODS:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Write permissions are only allowed to the owner of the snippet.
|
||||||
|
return obj.owner == request.user
|
||||||
|
|
||||||
|
class IsOwnerOrNot(permissions.BasePermission):
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
r = Rower.objects.get(user=request.user)
|
||||||
|
return (obj.user == r)
|
||||||
105
rowers/serializers.py
Normal file
105
rowers/serializers.py
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from rowers.models import Workout,Rower
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
# Serializers define the API representation.
|
||||||
|
class RowerSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Rower
|
||||||
|
fields = (
|
||||||
|
'weightcategory',
|
||||||
|
'max',
|
||||||
|
'rest',
|
||||||
|
'ut2',
|
||||||
|
'ut1',
|
||||||
|
'at',
|
||||||
|
'tr',
|
||||||
|
'an',
|
||||||
|
'ftp',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkoutSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Workout
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'date',
|
||||||
|
'workouttype',
|
||||||
|
'starttime',
|
||||||
|
'distance',
|
||||||
|
'duration',
|
||||||
|
'averagehr',
|
||||||
|
'maxhr',
|
||||||
|
'notes',
|
||||||
|
'summary',
|
||||||
|
)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
r = Rower.objects.get(user=self.context['request'].user)
|
||||||
|
d = validated_data['date']
|
||||||
|
t = validated_data['starttime']
|
||||||
|
rowdatetime = datetime.datetime(d.year,
|
||||||
|
d.month,
|
||||||
|
d.day,
|
||||||
|
t.hour,
|
||||||
|
t.minute,
|
||||||
|
t.second)
|
||||||
|
w = Workout(user=r,
|
||||||
|
name=validated_data['name'],
|
||||||
|
date=validated_data['date'],
|
||||||
|
workouttype=validated_data['workouttype'],
|
||||||
|
duration=validated_data['duration'],
|
||||||
|
distance=validated_data['distance'],
|
||||||
|
weightcategory=r.weightcategory,
|
||||||
|
starttime=validated_data['starttime'],
|
||||||
|
csvfilename='',
|
||||||
|
notes=validated_data['notes'],
|
||||||
|
uploadedtoc2=0,
|
||||||
|
summary=validated_data['summary'],
|
||||||
|
averagehr=validated_data['averagehr'],
|
||||||
|
maxhr=validated_data['maxhr'],
|
||||||
|
startdatetime=rowdatetime)
|
||||||
|
w.save()
|
||||||
|
return w
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
d = validated_data['date']
|
||||||
|
t = validated_data['starttime']
|
||||||
|
rowdatetime = datetime.datetime(d.year,
|
||||||
|
d.month,
|
||||||
|
d.day,
|
||||||
|
t.hour,
|
||||||
|
t.minute,
|
||||||
|
t.second)
|
||||||
|
|
||||||
|
|
||||||
|
instance.name=validated_data['name']
|
||||||
|
instance.date=validated_data['date']
|
||||||
|
instance.workouttype=validated_data['workouttype']
|
||||||
|
instance.duration=validated_data['duration']
|
||||||
|
instance.distance=validated_data['distance']
|
||||||
|
instance.starttime=validated_data['starttime']
|
||||||
|
instance.notes=validated_data['notes']
|
||||||
|
instance.summary=validated_data['summary']
|
||||||
|
instance.averagehr=validated_data['averagehr']
|
||||||
|
instance.maxhr=validated_data['maxhr']
|
||||||
|
instance.startdatetime=rowdatetime
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
class StrokeDataSerializer(serializers.Serializer):
|
||||||
|
workoutid = serializers.IntegerField
|
||||||
|
strokedata = serializers.JSONField
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
"""
|
||||||
|
Create and enter a new set of stroke data into the DB
|
||||||
|
"""
|
||||||
|
|
||||||
|
# do something
|
||||||
|
print "fake serializer"
|
||||||
|
return 1
|
||||||
|
|
||||||
25
rowers/templates/strokedata_form.html
Normal file
25
rowers/templates/strokedata_form.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Change Rower {% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if form.errors %}
|
||||||
|
<p style="color: red;">
|
||||||
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<div class="grid_12 alpha">
|
||||||
|
<h1>Stroke Data for workout {{ id }}</h1>
|
||||||
|
|
||||||
|
<form enctype="multipart/form-data" action="/rowers/api/workouts/{{ id }}/strokedata" method="post">
|
||||||
|
<table>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="grid_2 prefix_2 suffix_2">
|
||||||
|
<input class="button green" type="submit" value="POST">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
1
rowers/testdata/strokedata.txt
vendored
Normal file
1
rowers/testdata/strokedata.txt
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
|||||||
from django.test import TestCase, Client
|
from django.test import TestCase, Client,override_settings
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
from .views import checkworkoutuser,c2_open
|
from .views import checkworkoutuser,c2_open
|
||||||
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
from rowers.models import Workout, User, Rower, WorkoutForm,RowerForm,GraphImage
|
||||||
@@ -24,6 +24,11 @@ import numpy as np
|
|||||||
from rowers import urls
|
from rowers import urls
|
||||||
from rowers.views import error500_view,error404_view,error400_view,error403_view
|
from rowers.views import error500_view,error404_view,error400_view,error403_view
|
||||||
|
|
||||||
|
from dataprep import delete_strokedata
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DjangoTestCase(TestCase, MockTestCase):
|
class DjangoTestCase(TestCase, MockTestCase):
|
||||||
def _pre_setup(self):
|
def _pre_setup(self):
|
||||||
MockTestCase.setUp(self)
|
MockTestCase.setUp(self)
|
||||||
@@ -33,6 +38,7 @@ class DjangoTestCase(TestCase, MockTestCase):
|
|||||||
def _post_teardown(self):
|
def _post_teardown(self):
|
||||||
TestCase._post_teardown(self)
|
TestCase._post_teardown(self)
|
||||||
MockTestCase.tearDown(self)
|
MockTestCase.tearDown(self)
|
||||||
|
delete_strokedata(1)
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
||||||
@@ -149,6 +155,7 @@ class STObjects(DjangoTestCase):
|
|||||||
|
|
||||||
class TestErrorPages(TestCase):
|
class TestErrorPages(TestCase):
|
||||||
def test_error_handlers(self):
|
def test_error_handlers(self):
|
||||||
|
|
||||||
self.assertTrue(urls.handler404.endswith('.error404_view'))
|
self.assertTrue(urls.handler404.endswith('.error404_view'))
|
||||||
self.assertTrue(urls.handler500.endswith('.error500_view'))
|
self.assertTrue(urls.handler500.endswith('.error500_view'))
|
||||||
factory = RequestFactory()
|
factory = RequestFactory()
|
||||||
@@ -315,13 +322,12 @@ class DataTest(TestCase):
|
|||||||
|
|
||||||
form = DocumentsForm(form_data,file_data)
|
form = DocumentsForm(form_data,file_data)
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
u = User.objects.get(username='john')
|
u = User.objects.get(username='john')
|
||||||
r = Rower.objects.get(user=u)
|
r = Rower.objects.get(user=u)
|
||||||
|
|
||||||
|
|
||||||
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
rr = rrower(hrmax=r.max,hrut2=r.ut2,
|
||||||
hrut1=r.ut1,hrat=r.at,
|
hrut1=r.ut1,hrat=r.at,
|
||||||
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
hrtr=r.tr,hran=r.an,ftp=r.ftp)
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from models import Workout,Rower
|
||||||
|
|
||||||
|
from rest_framework import routers, serializers, viewsets,permissions
|
||||||
|
from rest_framework.urlpatterns import format_suffix_patterns
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
@@ -8,6 +14,20 @@ from django.conf.urls import (
|
|||||||
handler400, handler403, handler404, handler500,
|
handler400, handler403, handler404, handler500,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from rowers.permissions import IsOwnerOrNot,IsOwnerOrReadOnly
|
||||||
|
from rowers.serializers import WorkoutSerializer,RowerSerializer
|
||||||
|
|
||||||
|
class WorkoutViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = Workout.objects.all().order_by("-date", "-starttime")
|
||||||
|
serializer_class = WorkoutSerializer
|
||||||
|
permission_classes = (IsOwnerOrNot,)
|
||||||
|
|
||||||
|
|
||||||
|
# Routers provide an easy way of automatically determining the URL conf.
|
||||||
|
router = routers.DefaultRouter()
|
||||||
|
router.register(r'api/workouts',WorkoutViewSet)
|
||||||
|
#router.register(r'api/rower',RowerViewSet)
|
||||||
|
|
||||||
handler500 = 'views.error500_view'
|
handler500 = 'views.error500_view'
|
||||||
handler404 = 'views.error404_view'
|
handler404 = 'views.error404_view'
|
||||||
handler400 = 'views.error400_view'
|
handler400 = 'views.error400_view'
|
||||||
@@ -16,6 +36,11 @@ handler403 = 'views.error403_view'
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# url(r'^password_change/$',auth_views.password_change),
|
# url(r'^password_change/$',auth_views.password_change),
|
||||||
# url(r'^password_change_done/$',auth_views.password_change_done),
|
# url(r'^password_change_done/$',auth_views.password_change_done),
|
||||||
|
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
|
||||||
|
url(r'^', include(router.urls)),
|
||||||
|
url(r'^api-docs$', views.schema_view),
|
||||||
|
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||||
|
url(r'^api/workouts/(\d+)/strokedata$',views.strokedatajson),
|
||||||
url(r'^testbokeh$',views.testbokeh),
|
url(r'^testbokeh$',views.testbokeh),
|
||||||
url(r'^500/$', TemplateView.as_view(template_name='500.html'),name='500'),
|
url(r'^500/$', TemplateView.as_view(template_name='500.html'),name='500'),
|
||||||
url(r'^404/$', TemplateView.as_view(template_name='404.html'),name='404'),
|
url(r'^404/$', TemplateView.as_view(template_name='404.html'),name='404'),
|
||||||
@@ -138,6 +163,8 @@ urlpatterns = [
|
|||||||
url(r'^workout/(?P<id>\d+)/flexchart$',views.workout_flexchart3_view),
|
url(r'^workout/(?P<id>\d+)/flexchart$',views.workout_flexchart3_view),
|
||||||
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/(?P<plottype>\w+.*)$',views.workout_comparison_view2),
|
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/(?P<plottype>\w+.*)$',views.workout_comparison_view2),
|
||||||
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/$',views.workout_comparison_view2),
|
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>\w+.*)/$',views.workout_comparison_view2),
|
||||||
|
url(r'^test\_callback',views.rower_process_testcallback),
|
||||||
|
url(r'^workout/(\d+)/test\_strokedata$',views.strokedataform),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
@@ -146,3 +173,5 @@ if settings.DEBUG:
|
|||||||
url(r'^testreverse/$',views.test_reverse_view),
|
url(r'^testreverse/$',views.test_reverse_view),
|
||||||
url(r'^c2listug/$',views.c2listdebug_view),
|
url(r'^c2listug/$',views.c2listdebug_view),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
#urlpatterns = format_suffix_patterns(urlpatterns)
|
||||||
|
|||||||
224
rowers/views.py
224
rowers/views.py
@@ -15,7 +15,7 @@ from django.utils import timezone,translation
|
|||||||
from django.core.mail import send_mail, BadHeaderError
|
from django.core.mail import send_mail, BadHeaderError
|
||||||
from rowers.forms import EmailForm, RegistrationForm, RegistrationFormTermsOfService,RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm,UpdateStreamForm
|
from rowers.forms import EmailForm, RegistrationForm, RegistrationFormTermsOfService,RegistrationFormUniqueEmail,CNsummaryForm,UpdateWindForm,UpdateStreamForm
|
||||||
from rowers.forms import PredictedPieceForm,DateRangeForm,DeltaDaysForm
|
from rowers.forms import PredictedPieceForm,DateRangeForm,DeltaDaysForm
|
||||||
from rowers.forms import SummaryStringForm,IntervalUpdateForm
|
from rowers.forms import SummaryStringForm,IntervalUpdateForm,StrokeDataForm
|
||||||
from rowers.models import Workout, User, Rower, WorkoutForm
|
from rowers.models import Workout, User, Rower, WorkoutForm
|
||||||
from rowers.models import RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm
|
from rowers.models import RowerPowerForm,RowerForm,GraphImage,AdvancedWorkoutForm
|
||||||
import StringIO
|
import StringIO
|
||||||
@@ -29,10 +29,14 @@ from c2stuff import C2NoTokenError
|
|||||||
from iso8601 import ParseError
|
from iso8601 import ParseError
|
||||||
import stravastuff
|
import stravastuff
|
||||||
import sporttracksstuff
|
import sporttracksstuff
|
||||||
|
import ownapistuff
|
||||||
|
from ownapistuff import TEST_CLIENT_ID, TEST_CLIENT_SECRET, TEST_REDIRECT_URI
|
||||||
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET
|
from rowsandall_app.settings import C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET, STRAVA_CLIENT_ID, STRAVA_REDIRECT_URI, STRAVA_CLIENT_SECRET
|
||||||
from rowsandall_app.settings import SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI, SPORTTRACKS_CLIENT_SECRET
|
from rowsandall_app.settings import SPORTTRACKS_CLIENT_ID, SPORTTRACKS_REDIRECT_URI, SPORTTRACKS_CLIENT_SECRET
|
||||||
import requests
|
import requests
|
||||||
import json
|
import json
|
||||||
|
from rest_framework.renderers import JSONRenderer
|
||||||
|
from rest_framework.parsers import JSONParser
|
||||||
from rowsandall_app.rows import handle_uploaded_file
|
from rowsandall_app.rows import handle_uploaded_file
|
||||||
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
|
from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv
|
||||||
from rowers.tasks import handle_sendemail_unrecognized
|
from rowers.tasks import handle_sendemail_unrecognized
|
||||||
@@ -64,6 +68,16 @@ queue = django_rq.get_queue('default')
|
|||||||
queuelow = django_rq.get_queue('low')
|
queuelow = django_rq.get_queue('low')
|
||||||
queuehigh = django_rq.get_queue('low')
|
queuehigh = django_rq.get_queue('low')
|
||||||
|
|
||||||
|
from rest_framework_swagger.views import get_swagger_view
|
||||||
|
from rest_framework.renderers import JSONRenderer
|
||||||
|
from rest_framework.parsers import JSONParser
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rowers.serializers import RowerSerializer,WorkoutSerializer
|
||||||
|
from rest_framework import status,permissions,generics
|
||||||
|
from rest_framework.decorators import api_view
|
||||||
|
|
||||||
|
from permissions import IsOwnerOrNot
|
||||||
|
|
||||||
import plots
|
import plots
|
||||||
import mailprocessing
|
import mailprocessing
|
||||||
|
|
||||||
@@ -77,6 +91,10 @@ USER_LANGUAGE = 'en-US'
|
|||||||
|
|
||||||
from interactiveplots import *
|
from interactiveplots import *
|
||||||
|
|
||||||
|
schema_view = get_swagger_view(title='Rowsandall API (Unstable)')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def error500_view(request):
|
def error500_view(request):
|
||||||
response = render_to_response('500.html', {},
|
response = render_to_response('500.html', {},
|
||||||
context_instance = RequestContext(request))
|
context_instance = RequestContext(request))
|
||||||
@@ -1153,6 +1171,7 @@ def rower_process_stravacallback(request):
|
|||||||
return imports_view(request,successmessage=successmessage)
|
return imports_view(request,successmessage=successmessage)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def rower_process_sporttrackscallback(request):
|
def rower_process_sporttrackscallback(request):
|
||||||
code = request.GET['code']
|
code = request.GET['code']
|
||||||
@@ -1174,6 +1193,26 @@ def rower_process_sporttrackscallback(request):
|
|||||||
successmessage = "Tokens stored. Good to go"
|
successmessage = "Tokens stored. Good to go"
|
||||||
return imports_view(request,successmessage=successmessage)
|
return imports_view(request,successmessage=successmessage)
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def rower_process_testcallback(request):
|
||||||
|
code = request.GET['code']
|
||||||
|
res = ownapistuff.get_token(code)
|
||||||
|
|
||||||
|
|
||||||
|
access_token = res[0]
|
||||||
|
expires_in = res[1]
|
||||||
|
refresh_token = res[2]
|
||||||
|
expirydatetime = timezone.now()+datetime.timedelta(seconds=expires_in)
|
||||||
|
|
||||||
|
text = "Access Token:\n"
|
||||||
|
text += access_token
|
||||||
|
|
||||||
|
text += "\n\nRefresh Token:\n"
|
||||||
|
text += refresh_token
|
||||||
|
|
||||||
|
return HttpResponse(text)
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
def histo_all(request,theuser=0):
|
def histo_all(request,theuser=0):
|
||||||
promember=0
|
promember=0
|
||||||
@@ -1867,7 +1906,7 @@ def workouts_view(request,message='',successmessage='',
|
|||||||
'enddate':enddate,
|
'enddate':enddate,
|
||||||
})
|
})
|
||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("Admin has no rower instance")
|
return HttpResponse("User has no rower instance")
|
||||||
|
|
||||||
@user_passes_test(promember,login_url="/login")
|
@user_passes_test(promember,login_url="/login")
|
||||||
def workout_comparison_list(request,id=0,message='',successmessage='',
|
def workout_comparison_list(request,id=0,message='',successmessage='',
|
||||||
@@ -1942,7 +1981,7 @@ def workout_comparison_list(request,id=0,message='',successmessage='',
|
|||||||
'enddate':enddate,
|
'enddate':enddate,
|
||||||
})
|
})
|
||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("Admin has no rower instance")
|
return HttpResponse("User has no rower instance")
|
||||||
|
|
||||||
def workout_view(request,id=0):
|
def workout_view(request,id=0):
|
||||||
try:
|
try:
|
||||||
@@ -2859,17 +2898,16 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
|||||||
u = request.user
|
u = request.user
|
||||||
r = Rower.objects.get(user=u)
|
r = Rower.objects.get(user=u)
|
||||||
|
|
||||||
res = interactive_chart(id)
|
|
||||||
script = res[0]
|
|
||||||
div = res[1]
|
|
||||||
|
|
||||||
rowdata = rdata(f1)
|
rowdata = rdata(f1)
|
||||||
hascoordinates = 1
|
hascoordinates = 1
|
||||||
try:
|
if rowdata != 0:
|
||||||
latitude = rowdata.df[' latitude']
|
try:
|
||||||
except KeyError:
|
latitude = rowdata.df[' latitude']
|
||||||
hascoordinates = 0
|
except KeyError,AttributeError:
|
||||||
|
hascoordinates = 0
|
||||||
|
else:
|
||||||
|
hascoordinates = 0
|
||||||
|
|
||||||
if hascoordinates:
|
if hascoordinates:
|
||||||
res = googlemap_chart(rowdata.df[' latitude'],
|
res = googlemap_chart(rowdata.df[' latitude'],
|
||||||
rowdata.df[' longitude'],
|
rowdata.df[' longitude'],
|
||||||
@@ -2892,8 +2930,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
|||||||
'gmscript': gmscript,
|
'gmscript': gmscript,
|
||||||
'gmdiv': gmdiv,
|
'gmdiv': gmdiv,
|
||||||
})
|
})
|
||||||
# 'interactiveplot':script,
|
|
||||||
# 'the_div':div})
|
|
||||||
else:
|
else:
|
||||||
return render(request, 'workout_form.html',
|
return render(request, 'workout_form.html',
|
||||||
{'form':form,
|
{'form':form,
|
||||||
@@ -2905,8 +2942,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
|
|||||||
'gmscript': gmscript,
|
'gmscript': gmscript,
|
||||||
'gmdiv': gmdiv,
|
'gmdiv': gmdiv,
|
||||||
})
|
})
|
||||||
# 'interactiveplot':script,
|
|
||||||
# 'the_div':div})
|
|
||||||
|
|
||||||
except Workout.DoesNotExist:
|
except Workout.DoesNotExist:
|
||||||
form = WorkoutForm(
|
form = WorkoutForm(
|
||||||
@@ -3644,6 +3680,8 @@ def workout_upload_view(request,message=""):
|
|||||||
startdatetime=workoutstartdatetime)
|
startdatetime=workoutstartdatetime)
|
||||||
|
|
||||||
w.save()
|
w.save()
|
||||||
|
# put stroke data in database
|
||||||
|
res = dataprep.dataprep(row.df,id=w.id,bands=True,barchart=True,otwpower=True)
|
||||||
|
|
||||||
# Make Plot
|
# Make Plot
|
||||||
if (make_plot):
|
if (make_plot):
|
||||||
@@ -3716,7 +3754,7 @@ def workout_upload_view(request,message=""):
|
|||||||
'user-agent': 'sanderroosendaal',
|
'user-agent': 'sanderroosendaal',
|
||||||
'Content-Type': 'application/json'}
|
'Content-Type': 'application/json'}
|
||||||
import urllib
|
import urllib
|
||||||
url = "https://log.concept2.com/api/users/%s/results" % (c2userid)
|
url = "httpvs://log.concept2.com/api/users/%s/results" % (c2userid)
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data))
|
||||||
|
|
||||||
# response = c2stuff.workout_c2_upload(request.user,w)
|
# response = c2stuff.workout_c2_upload(request.user,w)
|
||||||
@@ -4077,7 +4115,7 @@ def dashboard_view(request,message="",successmessage=""):
|
|||||||
'successmessage':successmessage})
|
'successmessage':successmessage})
|
||||||
|
|
||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("Admin has no rower instance")
|
return HttpResponse("User has no rower instance")
|
||||||
|
|
||||||
|
|
||||||
@login_required()
|
@login_required()
|
||||||
@@ -4104,7 +4142,7 @@ def graphs_view(request):
|
|||||||
{'graphs1': g[0:5],
|
{'graphs1': g[0:5],
|
||||||
'graphs2': g[5:10]})
|
'graphs2': g[5:10]})
|
||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("Admin has no rower instance")
|
return HttpResponse("User has no rower instance")
|
||||||
|
|
||||||
|
|
||||||
def graph_show_view(request,id):
|
def graph_show_view(request,id):
|
||||||
@@ -4435,4 +4473,150 @@ def rower_edit_view(request,message=""):
|
|||||||
except Rower.DoesNotExist:
|
except Rower.DoesNotExist:
|
||||||
return HttpResponse("This user doesn't exist")
|
return HttpResponse("This user doesn't exist")
|
||||||
|
|
||||||
|
class JSONResponse(HttpResponse):
|
||||||
|
def __init__(self, data, **kwargs):
|
||||||
|
content = JSONRenderer().render(data)
|
||||||
|
kwargs['content_type'] = 'application/json'
|
||||||
|
super(JSONResponse, self).__init__(content, **kwargs)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def trydf(df,aantal,column):
|
||||||
|
try:
|
||||||
|
s = df[column]
|
||||||
|
if len(s) != aantal:
|
||||||
|
return np.zeros(aantal)
|
||||||
|
if not np.issubdtype(s,np.number):
|
||||||
|
return np.zeros(aantal)
|
||||||
|
except KeyError:
|
||||||
|
s = np.zeros(aantal)
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
|
@login_required()
|
||||||
|
def strokedataform(request,id=0):
|
||||||
|
if request.method == 'GET':
|
||||||
|
form = StrokeDataForm()
|
||||||
|
return render(request, 'strokedata_form.html',
|
||||||
|
{
|
||||||
|
'form':form,
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
elif request.method == 'POST':
|
||||||
|
form = StrokeDataForm()
|
||||||
|
|
||||||
|
return render(request, 'strokedata_form.html',
|
||||||
|
{
|
||||||
|
'form':form,
|
||||||
|
'id':id,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
@csrf_exempt
|
||||||
|
@login_required()
|
||||||
|
def strokedatajson(request,id):
|
||||||
|
try:
|
||||||
|
row = Workout.objects.get(id=id)
|
||||||
|
if (checkworkoutuser(request.user,row)==False):
|
||||||
|
return HttpResponse("Permission error")
|
||||||
|
except Workout.DoesNotExist:
|
||||||
|
return HttpResponse("Workout doesn't exist")
|
||||||
|
try:
|
||||||
|
id = int(id)
|
||||||
|
except ValueError:
|
||||||
|
return HttpResponse("Not a valid workout number")
|
||||||
|
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
columns = ['spm','timesecs','hr','pseconds','power','distance']
|
||||||
|
datadf = dataprep.getsmallrowdata_db(columns,ids=[id])
|
||||||
|
return JSONResponse(datadf)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
checkdata,r = dataprep.getrowdata_db(id=row.id)
|
||||||
|
if not checkdata.empty:
|
||||||
|
return "Not OK 1"
|
||||||
|
# strokedata = request.POST['strokedata']
|
||||||
|
print request.body
|
||||||
|
received_json_data = json.loads(request.body)
|
||||||
|
# checking/validating and cleaning
|
||||||
|
try:
|
||||||
|
strokedata = json.loads(received_json_data['strokedata'])
|
||||||
|
except:
|
||||||
|
return HttpResponse("Not OK 2")
|
||||||
|
|
||||||
|
df = pd.DataFrame(strokedata)
|
||||||
|
df.index = df.index.astype(int)
|
||||||
|
df.sort_index(inplace=True)
|
||||||
|
# time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
|
||||||
|
time = df['timesecs']
|
||||||
|
aantal = len(time)
|
||||||
|
pace = df['pseconds']
|
||||||
|
if len(pace) != aantal:
|
||||||
|
return "Not OK"
|
||||||
|
distance = df['distance']
|
||||||
|
if len(distance) != aantal:
|
||||||
|
return "Not OK 3"
|
||||||
|
|
||||||
|
spm = df['spm']
|
||||||
|
if len(spm) != aantal:
|
||||||
|
return "Not OK 4"
|
||||||
|
|
||||||
|
res = dataprep.testdata(time,distance,pace,spm)
|
||||||
|
if not res:
|
||||||
|
return HttpResponse("Not OK 5")
|
||||||
|
|
||||||
|
power = trydf(df,aantal,'power')
|
||||||
|
drivelength = trydf(df,aantal,'drivelength')
|
||||||
|
drivespeed = trydf(df,aantal,'drivespeed')
|
||||||
|
dragfactor = trydf(df,aantal,'dragfactor')
|
||||||
|
drivetime = trydf(df,aantal,'drivetime')
|
||||||
|
strokerecoverytime = trydf(df,aantal,'strokerecoverytime')
|
||||||
|
averagedriveforce = trydf(df,aantal,'averagedriveforce')
|
||||||
|
peakdriveforce = trydf(df,aantal,'peakdriveforce')
|
||||||
|
lapidx = trydf(df,aantal,'lapidx')
|
||||||
|
hr = trydf(df,aantal,'hr')
|
||||||
|
|
||||||
|
starttime = totimestamp(row.startdatetime)+time
|
||||||
|
unixtime = starttime+time
|
||||||
|
|
||||||
|
data = pd.DataFrame({'TimeStamp (sec)':unixtime,
|
||||||
|
' Horizontal (meters)': distance,
|
||||||
|
' Cadence (stokes/min)':spm,
|
||||||
|
' HRCur (bpm)':hr,
|
||||||
|
' DragFactor':dragfactor,
|
||||||
|
' Stroke500mPace (sec/500m)':pace,
|
||||||
|
' Power (watts)':power,
|
||||||
|
' DriveLength (meters)':drivelength,
|
||||||
|
' DriveTime (ms)':drivetime,
|
||||||
|
' StrokeRecoveryTime (ms)':strokerecoverytime,
|
||||||
|
' AverageDriveForce (lbs)':averagedriveforce,
|
||||||
|
' PeakDriveForce (lbs)':peakdriveforce,
|
||||||
|
' lapIdx':lapidx,
|
||||||
|
' ElapsedTime (sec)':time,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
timestr = row.startdatetime.strftime("%Y%m%d-%H%M%S")
|
||||||
|
csvfilename ='media/Import_'+timestr+'.csv'
|
||||||
|
|
||||||
|
res = data.to_csv(csvfilename,index_label='index')
|
||||||
|
row.csvfilename = csvfilename
|
||||||
|
row.save()
|
||||||
|
|
||||||
|
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)
|
||||||
|
rowdata = rdata(row.csvfilename,rower=rr).df
|
||||||
|
|
||||||
|
datadf = dataprep.dataprep(rowdata,id=row.id,bands=True,barchart=True,otwpower=True)
|
||||||
|
# mangling
|
||||||
|
|
||||||
|
#
|
||||||
|
return HttpResponse("OK")
|
||||||
|
|||||||
@@ -47,16 +47,28 @@ INSTALLED_APPS = [
|
|||||||
'translation_manager',
|
'translation_manager',
|
||||||
'debug_toolbar',
|
'debug_toolbar',
|
||||||
'django_mailbox',
|
'django_mailbox',
|
||||||
|
'rest_framework',
|
||||||
|
'rest_framework_swagger',
|
||||||
|
'oauth2_provider',
|
||||||
|
'corsheaders',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = (
|
||||||
|
'oauth2_provider.backends.OAuth2Backend',
|
||||||
|
# Uncomment following if you want to access the admin
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
)
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = [
|
MIDDLEWARE_CLASSES = [
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.locale.LocaleMiddleware',
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
'corsheaders.middleware.CorsMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||||
|
'oauth2_provider.middleware.OAuth2TokenMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'debug_toolbar.middleware.DebugToolbarMiddleware',
|
'debug_toolbar.middleware.DebugToolbarMiddleware',
|
||||||
@@ -86,6 +98,8 @@ TEMPLATES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
CORS_ORIGIN_ALLOW_ALL = True
|
||||||
|
|
||||||
WSGI_APPLICATION = 'rowsandall_app.wsgi.application'
|
WSGI_APPLICATION = 'rowsandall_app.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
@@ -230,5 +244,26 @@ EMAIL_USE_TLS = True
|
|||||||
FORECAST_IO_KEY = "bc8196fbd89f11375c7dfc8aa6323c72"
|
FORECAST_IO_KEY = "bc8196fbd89f11375c7dfc8aa6323c72"
|
||||||
GMAPIKEY = "AIzaSyAgu1w9QSthaGPMLp8y9JedPoMc9sfEgJ8"
|
GMAPIKEY = "AIzaSyAgu1w9QSthaGPMLp8y9JedPoMc9sfEgJ8"
|
||||||
|
|
||||||
# test
|
# OAUTH2
|
||||||
|
|
||||||
|
OAUTH2_PROVIDER = {
|
||||||
|
# this is the list of available scopes
|
||||||
|
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# REST Framework
|
||||||
|
|
||||||
|
REST_FRAMEWORK = {
|
||||||
|
# Use Django's standard `django.contrib.auth` permissions,
|
||||||
|
# or allow read-only access for unauthenticated users.
|
||||||
|
'DEFAULT_PERMISSION_CLASSES': [
|
||||||
|
'rest_framework.permissions.IsAuthenticated'
|
||||||
|
],
|
||||||
|
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||||
|
'rest_framework.authentication.BasicAuthentication',
|
||||||
|
'rest_framework.authentication.SessionAuthentication',
|
||||||
|
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
|
||||||
|
),
|
||||||
|
'PAGE_SIZE': 20,
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from rowers import views as rowersviews
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
|
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
|
||||||
# url('^', include('django.contrib.auth.urls')),
|
# url('^', include('django.contrib.auth.urls')),
|
||||||
url(r'^$',rootview),
|
url(r'^$',rootview),
|
||||||
url(r'^version/$',version),
|
url(r'^version/$',version),
|
||||||
|
|||||||
Reference in New Issue
Block a user