Private
Public Access
1
0

further pepping

This commit is contained in:
Sander Roosendaal
2022-02-15 16:53:38 +01:00
parent fb98877b5f
commit 2fb011e876
4 changed files with 81 additions and 61 deletions

Binary file not shown.

View File

@@ -1,10 +1,7 @@
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
from rowers.views.statements import * from rowers.views.statements import *
from rowers.tasks import handle_calctrimp from rowers.tasks import handle_calctrimp
from rowers.opaque import encoder from rowers.opaque import encoder
import sys
import arrow import arrow
# Stroke data form to test API upload # Stroke data form to test API upload
@@ -85,7 +82,35 @@ def strokedatajson_v2(request, id):
POST: Add Stroke data to workout POST: Add Stroke data to workout
GET: Get stroke data of workout GET: Get stroke data of workout
This v2 API works on stroke based data dict: This v2 API works on stroke based data dict:
{"data": [{"hr": 110, "p": 3600, "spm": 53, "d": 6, "t": 12}, {"hr": 111, "p": 3600, "spm": 53, "d": 6, "t": 12}, {"hr": 111, "p": 3600, "spm": 64, "d": 6, "t": 22}, {"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 55}, {"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 82}, {"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 109}, {"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 133}, {"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157}, {"hr": 108, "p": 3577, "spm": 12, "d": 32, "t": 157}, {"hr": 108, "p": 3411, "spm": 12, "d": 32, "t": 157}, {"hr": 108, "p": 2649, "spm": 12, "d": 32, "t": 157}, {"hr": 108, "p": 3099, "spm": 12, "d": 32, "t": 157}, {"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157}, {"hr": 100, "p": 3600, "spm": 44, "d": 115, "t": 292}, {"hr": 99, "p": 3600, "spm": 27, "d": 129, "t": 305}, {"hr": 97, "p": 3600, "spm": 34, "d": 161, "t": 330}, {"hr": 96, "p": 3600, "spm": 25, "d": 177, "t": 344}, {"hr": 96, "p": 3494, "spm": 43, "d": 196, "t": 357}, {"hr": 98, "p": 2927, "spm": 26, "d": 235, "t": 377}, {"hr": 102, "p": 2718, "spm": 27, "d": 380, "t": 455}, {"hr": 102, "p": 2753, "spm": 9, "d": 398, "t": 472}, {"hr": 102, "p": 2864, "spm": 61, "d": 406, "t": 477}, {"hr": 101, "p": 2780, "spm": 15, "d": 484, "t": 515}, {"hr": 101, "p": 2365, "spm": 16, "d": 583, "t": 554}, {"hr": 103, "p": 1965, "spm": 16, "d": 681, "t": 592}, {"hr": 104, " {"data":
[
{"hr": 110, "p": 3600, "spm": 53, "d": 6, "t": 12},
{"hr": 111, "p": 3600, "spm": 53, "d": 6, "t": 12},
{"hr": 111, "p": 3600, "spm": 64, "d": 6, "t": 22},
{"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 55},
{"hr": 110, "p": 3600, "spm": 16, "d": 14, "t": 82},
{"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 109},
{"hr": 107, "p": 3600, "spm": 12, "d": 22, "t": 133},
{"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157},
{"hr": 108, "p": 3577, "spm": 12, "d": 32, "t": 157},
{"hr": 108, "p": 3411, "spm": 12, "d": 32, "t": 157},
{"hr": 108, "p": 2649, "spm": 12, "d": 32, "t": 157},
{"hr": 108, "p": 3099, "spm": 12, "d": 32, "t": 157},
{"hr": 108, "p": 3600, "spm": 12, "d": 32, "t": 157},
{"hr": 100, "p": 3600, "spm": 44, "d": 115, "t": 292},
{"hr": 99, "p": 3600, "spm": 27, "d": 129, "t": 305},
{"hr": 97, "p": 3600, "spm": 34, "d": 161, "t": 330},
{"hr": 96, "p": 3600, "spm": 25, "d": 177, "t": 344},
{"hr": 96, "p": 3494, "spm": 43, "d": 196, "t": 357},
{"hr": 98, "p": 2927, "spm": 26, "d": 235, "t": 377},
{"hr": 102, "p": 2718, "spm": 27, "d": 380, "t": 455},
{"hr": 102, "p": 2753, "spm": 9, "d": 398, "t": 472},
{"hr": 102, "p": 2864, "spm": 61, "d": 406, "t": 477},
{"hr": 101, "p": 2780, "spm": 15, "d": 484, "t": 515},
{"hr": 101, "p": 2365, "spm": 16, "d": 583, "t": 554},
{"hr": 103, "p": 1965, "spm": 16, "d": 681, "t": 592},
]
}
""" """
row = get_object_or_404(Workout, pk=id) row = get_object_or_404(Workout, pk=id)
@@ -144,7 +169,6 @@ def strokedatajson_v2(request, id):
df.index = df.index.astype(int) df.index = df.index.astype(int)
df.sort_index(inplace=True) df.sort_index(inplace=True)
#time, pace, distance,spm
try: try:
time = df['time']/1.e3 time = df['time']/1.e3
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
@@ -182,10 +206,6 @@ def strokedatajson_v2(request, id):
drivelength = df['drivelength'] drivelength = df['drivelength']
except KeyError: except KeyError:
drivelength = 0*time drivelength = 0*time
try:
drivespeed = df['drivespeed']
except KeyError:
drivespeed = 0*time
try: try:
dragfactor = df['dragfactor'] dragfactor = df['dragfactor']
except KeyError: except KeyError:
@@ -297,8 +317,7 @@ def strokedatajson_v2(request, id):
row.duplicate = True row.duplicate = True
row.save() row.save()
res = data.to_csv(csvfilename+'.gz', index_label='index', _ = data.to_csv(csvfilename+'.gz', index_label='index', compression='gzip')
compression='gzip')
row.csvfilename = csvfilename row.csvfilename = csvfilename
row.save() row.save()
@@ -320,8 +339,8 @@ def strokedatajson_v2(request, id):
datadf = dataprep.dataprep( datadf = dataprep.dataprep(
rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True) rowdata, id=row.id, bands=True, barchart=True, otwpower=True, empower=True)
job = myqueue(queuehigh, handle_calctrimp, row.id, _ = myqueue(queuehigh, handle_calctrimp, row.id,
row.csvfilename, r.ftp, r.sex, r.hrftp, r.max, r.rest) row.csvfilename, r.ftp, r.sex, r.hrftp, r.max, r.rest)
isbreakthrough, ishard = dataprep.checkbreakthrough(row, r) isbreakthrough, ishard = dataprep.checkbreakthrough(row, r)
@@ -332,9 +351,9 @@ def strokedatajson_v2(request, id):
'id': encoder.encode_hex(row.id), 'id': encoder.encode_hex(row.id),
} }
) )
email_sent = send_confirm(r.user, row.name, link, '') _ = send_confirm(r.user, row.name, link, '')
result = uploads.do_sync(row, {}, quick=True) _ = uploads.do_sync(row, {}, quick=True)
with open('apilog.log', 'a') as logfile: with open('apilog.log', 'a') as logfile:
logfile.write(str(timezone.now())+": ") logfile.write(str(timezone.now())+": ")
@@ -403,7 +422,6 @@ def strokedatajson(request, id=0):
return HttpResponse("Arrays must all be same length", status=400) return HttpResponse("Arrays must all be same length", status=400)
df.index = df.index.astype(int) df.index = df.index.astype(int)
df.sort_index(inplace=True) df.sort_index(inplace=True)
# time, hr, pace, spm, power, drivelength, distance, drivespeed, dragfactor, strokerecoverytime, averagedriveforce, peakdriveforce, lapidx
try: try:
time = df['time']/1.e3 time = df['time']/1.e3
except KeyError: # pragma: no cover except KeyError: # pragma: no cover
@@ -426,7 +444,6 @@ def strokedatajson(request, id=0):
power = trydf(df, aantal, 'power') power = trydf(df, aantal, 'power')
drivelength = trydf(df, aantal, 'drivelength') drivelength = trydf(df, aantal, 'drivelength')
drivespeed = trydf(df, aantal, 'drivespeed')
dragfactor = trydf(df, aantal, 'dragfactor') dragfactor = trydf(df, aantal, 'dragfactor')
drivetime = trydf(df, aantal, 'drivetime') drivetime = trydf(df, aantal, 'drivetime')
strokerecoverytime = trydf(df, aantal, 'strokerecoverytime') strokerecoverytime = trydf(df, aantal, 'strokerecoverytime')

View File

@@ -28,7 +28,9 @@ def paidplans_view(request):
if not request.user.is_anonymous: if not request.user.is_anonymous:
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
else: else:
r = None r = None
@@ -46,7 +48,9 @@ def billing_view(request):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
if payments.is_existing_customer(r): # pragma: no cover if payments.is_existing_customer(r): # pragma: no cover
url = reverse(upgrade_view) url = reverse(upgrade_view)
@@ -66,7 +70,7 @@ def billing_view(request):
if planselectform.is_valid(): if planselectform.is_valid():
plan = planselectform.cleaned_data['plan'] plan = planselectform.cleaned_data['plan']
try: try:
customer_id = braintreestuff.create_customer(r) _ = braintreestuff.create_customer(r)
except ProcessorCustomerError: # pragma: no cover except ProcessorCustomerError: # pragma: no cover
messages.error( messages.error(
request, "Something went wrong registering you as a customer.") request, "Something went wrong registering you as a customer.")
@@ -223,7 +227,7 @@ def purchase_checkouts_view(request):
amount, success = braintreestuff.make_payment(r, data) amount, success = braintreestuff.make_payment(r, data)
diff = plan.price - int(amount) diff = plan.price - int(amount)
eurocredits = credits.withdraw(diff, r) _ = credits.withdraw(diff, r)
if success: if success:
messages.info( messages.info(
@@ -258,13 +262,13 @@ def purchase_checkouts_view(request):
create_sessions_from_json(plansteps, r, startdate, r.user) create_sessions_from_json(plansteps, r, startdate, r.user)
job = myqueue(queuehigh, handle_send_email_instantplan_notification, _ = myqueue(queuehigh, handle_send_email_instantplan_notification,
r.user.username, r.user.username,
r.user.email, r.user.email,
plan.price, plan.price,
plan.name, plan.name,
startdate, startdate,
enddate) enddate)
url = reverse('plannedsessions_view') url = reverse('plannedsessions_view')
timeperiod = startdate.strftime( timeperiod = startdate.strftime(
@@ -280,9 +284,7 @@ def purchase_checkouts_view(request):
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
elif 'tac' not in request.POST: # pragma: no cover elif 'tac' not in request.POST: # pragma: no cover
try: try:
planid = int(request.POST['plan'])
enddate = request.POST['enddate'] enddate = request.POST['enddate']
rower = r.id
# incomplete # incomplete
except IndexError: except IndexError:
messages.error(request, "There was an error in the payment form") messages.error(request, "There was an error in the payment form")
@@ -355,7 +357,9 @@ def upgrade_view(request):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
url = reverse(billing_view) url = reverse(billing_view)
@@ -402,7 +406,9 @@ def downgrade_view(request):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
if r.subscription_id is None or r.subscription_id == '': # pragma: no cover if r.subscription_id is None or r.subscription_id == '': # pragma: no cover
url = reverse(billing_view) url = reverse(billing_view)
@@ -462,7 +468,9 @@ def plan_stop_view(request):
subscriptions = [] subscriptions = []
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree':
try: try:
@@ -516,7 +524,9 @@ def upgrade_confirm_view(request, planid=0):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
client_token = braintreestuff.get_client_token(r) client_token = braintreestuff.get_client_token(r)
@@ -571,7 +581,9 @@ def payment_confirm_view(request, planid=0):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only available through" \
" BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
client_token = braintreestuff.get_client_token(r) client_token = braintreestuff.get_client_token(r)
@@ -593,7 +605,10 @@ def checkouts_view(request):
r = request.user.rower r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring': # pragma: no cover
messages.error(request, 'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed') messages.error(request, 'Automated payment processing is currently only" \
" available through BrainTree (by PayPal). " \
"You are currently on a recurring payment plan with PayPal." \
" Contact the site administrator at support@rowsandall.com before you proceed')
if request.method != 'POST': # pragma: no cover if request.method != 'POST': # pragma: no cover
url = reverse(paidplans_view) url = reverse(paidplans_view)
@@ -785,7 +800,7 @@ def useractivate(request, uidb64, token): # pragma: no cover
template = 'coachregisteremail.html' template = 'coachregisteremail.html'
send_template_email(from_address, [fullemail], send_template_email(from_address, [fullemail],
subject, 'registeremail.html', d) subject, template, d)
subject2 = "New User" subject2 = "New User"
message2 = "New user registered.\n" message2 = "New user registered.\n"
@@ -820,7 +835,6 @@ def rower_register_view(request):
nextpage = '/rowers/list-workouts/' nextpage = '/rowers/list-workouts/'
if request.method == 'POST': if request.method == 'POST':
#form = RegistrationFormUniqueEmail(request.POST)
form = RegistrationFormSex(request.POST) form = RegistrationFormSex(request.POST)
if form.is_valid(): if form.is_valid():
first_name = form.cleaned_data['first_name'] first_name = form.cleaned_data['first_name']
@@ -870,12 +884,6 @@ def rower_register_view(request):
# Create and send email # Create and send email
current_site = get_current_site(request) current_site = get_current_site(request)
mail_subject = 'Activate your account.' mail_subject = 'Activate your account.'
d = {
'user': theuser,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(theuser.id)),
'token': account_activation_token.make_token(theuser),
}
to_email = form.cleaned_data.get('email') to_email = form.cleaned_data.get('email')
message = render_to_string('acc_activate_email.html', { message = render_to_string('acc_activate_email.html', {
'user': theuser, 'user': theuser,
@@ -917,7 +925,6 @@ def freecoach_register_view(request): # pragma: no cover
nextpage = '/rowers/me/teams/' nextpage = '/rowers/me/teams/'
if request.method == 'POST': if request.method == 'POST':
#form = RegistrationFormUniqueEmail(request.POST)
form = RegistrationFormSex(request.POST) form = RegistrationFormSex(request.POST)
if form.is_valid(): if form.is_valid():
first_name = form.cleaned_data['first_name'] first_name = form.cleaned_data['first_name']
@@ -951,12 +958,6 @@ def freecoach_register_view(request): # pragma: no cover
# Create and send email # Create and send email
current_site = get_current_site(request) current_site = get_current_site(request)
mail_subject = 'Activate your account.' mail_subject = 'Activate your account.'
d = {
'user': theuser,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(theuser.id)).decode(),
'token': account_activation_token.make_token(theuser),
}
to_email = form.cleaned_data.get('email') to_email = form.cleaned_data.get('email')
message = render_to_string('acc_activate_email.html', { message = render_to_string('acc_activate_email.html', {
'user': theuser, 'user': theuser,

View File

@@ -144,8 +144,8 @@ def rower_calcdps_view(request):
r = getrower(request.user) r = getrower(request.user)
ws = [(w.id, w.csvfilename) for w in Workout.objects.filter(user=r)] ws = [(w.id, w.csvfilename) for w in Workout.objects.filter(user=r)]
res = myqueue(queue, handle_updatedps, r.user.email, ws, debug=False, _ = myqueue(queue, handle_updatedps, r.user.email, ws, debug=False,
emailbounced=r.emailbounced) emailbounced=r.emailbounced)
messages.info( messages.info(
request, "Your workouts are being updated in the background. You will receive email when this is done.") request, "Your workouts are being updated in the background. You will receive email when this is done.")
@@ -295,9 +295,7 @@ def invitation_revoke_view(request, id):
res, text = teams.revoke_invite(request.user, id) res, text = teams.revoke_invite(request.user, id)
if res: if res:
messages.info(request, text) messages.info(request, text)
successmessage = text
else: # pragma: no cover else: # pragma: no cover
message = text
messages.error(request, text) messages.error(request, text)
url = reverse(rower_teams_view) url = reverse(rower_teams_view)
@@ -358,7 +356,8 @@ def athlete_drop_coach_confirm_view(request, id):
return render(request, 'dropcoachconfirm.html', return render(request, 'dropcoachconfirm.html',
{ {
'rower': r, 'rower': r,
'coach': coach 'coach': coach,
'breadcrumbs': breadcrumbs,
}) })
@@ -386,7 +385,8 @@ def coach_drop_athlete_confirm_view(request, id):
return render(request, 'dropathleteconfirm.html', return render(request, 'dropathleteconfirm.html',
{ {
'rower': r, 'rower': r,
'athlete': rower 'athlete': rower,
'breadcrumbs': breadcrumbs,
}) })
@@ -448,7 +448,8 @@ def team_requestmembership_view(request, teamid, userid):
# if t.manager.rower.rowerplan in ['plan','pro'] and r.rowerplan == 'basic': # if t.manager.rower.rowerplan in ['plan','pro'] and r.rowerplan == 'basic':
if not can_join_team(r.user, t): if not can_join_team(r.user, t):
messages.error(request, messages.error(request,
"You have to be on a paid plan (Pro or higher) to join this team. As a basic user you can only join teams managed by users on the Coach plan.") "You have to be on a paid plan (Pro or higher) to join this team."
" As a basic user you can only join teams managed by users on the Coach plan.")
url = reverse('paidplans_view') url = reverse('paidplans_view')
return HttpResponseRedirect(url) return HttpResponseRedirect(url)
@@ -468,8 +469,6 @@ def team_requestmembership_view(request, teamid, userid):
@login_required() @login_required()
def request_coaching_view(request, coachid): def request_coaching_view(request, coachid):
r = getrequestrower(request)
coach = User.objects.get(id=coachid).rower coach = User.objects.get(id=coachid).rower
if 'coach' in coach.rowerplan: if 'coach' in coach.rowerplan:
@@ -715,6 +714,7 @@ def team_create_view(request):
'memberteams': memberteams, 'memberteams': memberteams,
'otherteams': otherteams, 'otherteams': otherteams,
'active': 'nav-teams', 'active': 'nav-teams',
'rower': r,
'breadcrumbs': breadcrumbs, 'breadcrumbs': breadcrumbs,
}) })
@@ -749,6 +749,8 @@ def team_deleteconfirm_view(request, team_id):
'myteams': myteams, 'myteams': myteams,
'memberteams': memberteams, 'memberteams': memberteams,
'otherteams': otherteams, 'otherteams': otherteams,
'rower': r,
'breadcrumbs': breadcrumbs,
'active': 'nav-teams', 'active': 'nav-teams',
}) })
@@ -756,7 +758,6 @@ def team_deleteconfirm_view(request, team_id):
@login_required() @login_required()
@permission_required('teams.delete_team', fn=get_team_by_pk, raise_exception=True) @permission_required('teams.delete_team', fn=get_team_by_pk, raise_exception=True)
def team_delete_view(request, team_id): def team_delete_view(request, team_id):
r = getrower(request.user)
t = get_object_or_404(Team, pk=team_id) t = get_object_or_404(Team, pk=team_id)
teams.remove_team(t.id) teams.remove_team(t.id)
@@ -803,6 +804,7 @@ def team_members_stats_view(request, team_id):
'active': 'nav-teams', 'active': 'nav-teams',
'breadcrumbs': breadcrumbs, 'breadcrumbs': breadcrumbs,
'team': t, 'team': t,
'rower': r,
'theusers': theusers, 'theusers': theusers,
}) })