You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
padelclub_backend/tournaments/views.py

922 lines
37 KiB

# Standard library imports
import os
import csv
import json
import time
import asyncio
from datetime import date, datetime, timedelta
# Third-party imports
from qr_code.qrcode.utils import QRCodeOptions
# Django imports
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, JsonResponse, Http404
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.encoding import force_str, force_bytes
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.template import loader
from django.template.loader import render_to_string
from django.contrib import messages
from django.contrib.sites.shortcuts import get_current_site
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import (
UserCreationForm,
SetPasswordForm,
)
from django.contrib.auth.views import PasswordResetConfirmView
from django.contrib.auth.models import User
from django.contrib.auth.tokens import default_token_generator
from django.db.models import Q
from django.views.decorators.csrf import csrf_exempt
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.core.mail import EmailMessage
# Local application imports
from .models import (
Court,
DateInterval,
Club,
Tournament,
CustomUser,
Event,
Round,
GroupStage,
Match,
TeamScore,
TeamRegistration,
PlayerRegistration,
Purchase,
FailedApiCall,
TeamSummon,
FederalCategory,
)
from .forms import (
SimpleForm,
SimpleCustomUserCreationForm,
TournamentRegistrationForm,
AddPlayerForm,
ProfileUpdateForm,
)
from .utils.apns import send_push_notification
from .utils.licence_validator import LicenseValidator
from .utils.player_search import get_player_name_from_csv
from api.tokens import account_activation_token
from tournaments.models.device_token import DeviceToken
from tournaments.models.player_enums import PlayerDataSource, PlayerSexType
from django.views.generic.edit import UpdateView
def index(request):
club_id = request.GET.get('club')
future = future_tournaments(club_id)
live = live_tournaments(club_id)
finished = finished_tournaments(club_id)
club = None
if club_id:
club = get_object_or_404(Club, pk=club_id)
return render(
request,
"tournaments/tournaments.html",
{
'future': future[:10],
'live': live[:10],
'ended': finished[:10],
'club': club,
}
)
def tournaments_query(query, club_id, ascending):
queries = [query, Q(is_private=False, is_deleted=False, event__club__isnull=False)]
club = None
if club_id:
club = get_object_or_404(Club, pk=club_id)
q_club = Q(event__club=club)
queries.append(q_club)
sortkey = 'start_date'
if not ascending:
sortkey = '-start_date'
return Tournament.objects.filter(*queries).order_by(sortkey)
def finished_tournaments(club_id):
ended_tournaments = tournaments_query(Q(end_date__isnull=False), club_id, False)
return [t for t in ended_tournaments if t.display_tournament()]
def live_tournaments(club_id):
tournaments = tournaments_query(Q(end_date__isnull=True), club_id, True)
return [t for t in tournaments if t.display_tournament() and t.supposedly_in_progress()]
def future_tournaments(club_id):
tomorrow = datetime.now().date() + timedelta(days=1)
tournaments = tournaments_query(Q(end_date__isnull=True, start_date__gte=tomorrow), club_id, True)
return [t for t in tournaments if t.display_tournament()]
def tournament_info(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
registered_user = None
team_registration = None
is_captain = False
if request.user.is_authenticated:
# Assuming user's licence_id is stored in the user profile (e.g., request.user.licence_id)
user_licence_id = request.user.licence_id
if user_licence_id is not None:
validator = LicenseValidator(user_licence_id)
stripped_license = validator.stripped_license
# Check if there is a PlayerRegistration for this user in this tournament
registered_user = PlayerRegistration.objects.filter(
licence_id__startswith=stripped_license,
team_registration__tournament=tournament
).first()
# If the user is registered, retrieve their team registration
if registered_user:
is_captain = registered_user.captain
team_registration = registered_user.team_registration
return render(request, 'tournaments/tournament_info.html', {
'tournament': tournament,
'team': team_registration,
'is_captain': is_captain
})
def tournaments(request):
filter = int(request.GET.get('filter'))
club_id = request.GET.get('club')
title = ''
tournaments = []
if filter==0:
title = 'À venir'
tournaments = future_tournaments(club_id)
elif filter==1:
title = 'En cours'
tournaments = live_tournaments(club_id)
elif filter==2:
title = 'Terminés'
tournaments = finished_tournaments(club_id)
return render(
request,
"tournaments/tournaments_list.html",
{
'tournaments': tournaments,
'title': title,
'club': club_id,
}
)
def clubs(request):
all_clubs = Club.objects.all().order_by('name')
clubs = []
for club in all_clubs:
if club.events_count() > 0:
clubs.append(club)
return render(request, 'tournaments/clubs.html', {
'clubs': clubs,
})
def club(request, club_id):
club = get_object_or_404(Club, pk=club_id)
return render(request, 'tournaments/summons.html', {
'tournament': tournament,
'team_summons': team_summons,
})
def tournament(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
round_id = request.GET.get('round')
group_stage_id = request.GET.get('group_stage')
match_groups = tournament.match_groups(False, group_stage_id, round_id)
bracket_rounds = tournament.round_set.filter(parent=None, group_stage_loser_bracket=False).order_by('-index')
rounds = list(tournament.round_set.filter(group_stage_loser_bracket=True))
rounds.extend(bracket_rounds)
group_stages = sorted(tournament.get_computed_group_stage(), key=lambda s: (s.step, s.index))
if tournament.display_matches() or tournament.display_group_stages():
return render(request, 'tournaments/matches.html', {
'tournament': tournament,
'rounds': rounds,
'group_stages': group_stages,
'match_groups': match_groups,
})
else:
return tournament_info(request, tournament_id)
def tournament_teams(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
teams = tournament.teams(True)
return render(request, 'tournaments/teams.html', {
'tournament': tournament,
'teams': teams,
})
def tournament_summons(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
team_summons = tournament.team_summons()
return render(request, 'tournaments/summons.html', {
'tournament': tournament,
'team_summons': team_summons,
})
def tournament_broadcasted_summons(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcasted_summons.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def tournament_summons_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
team_summons = [summon.to_dict() for summon in tournament.team_summons()]
data = json.dumps(team_summons)
return HttpResponse(data, content_type='application/json')
def tournament_broadcast_home(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcast.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def automatic_broadcast(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcasted_auto.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def automatic_broadcast_event(request, event_id):
event = get_object_or_404(Event, pk=event_id)
tournaments = Tournament.objects.filter(event=event)
tournament_ids = [str(tournament.id) for tournament in tournaments]
return render(request, 'tournaments/broadcast/broadcasted_auto_event.html', {
'tournament_ids': tournament_ids,
})
def qr_code_url(request, tournament_id):
qr_code_url = reverse('tournament', args=[tournament_id])
return request.build_absolute_uri(qr_code_url)
def qr_code_url_with_query(request, club_id):
url_with_query = f"{request.build_absolute_uri('/')}?club={str(club_id)}"
return url_with_query
def qr_code_options():
return QRCodeOptions(size=10, border=4, error_correction='L')
def tournament_matches(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcasted_matches.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def broadcast_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
broadcast = tournament.broadcast_content()
data = json.dumps(broadcast)
return HttpResponse(data, content_type='application/json')
def tournament_matches_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
matches, group_stages = tournament.broadcasted_matches_and_group_stages()
live_matches = [match.live_match() for match in matches]
data = json.dumps(live_matches, default=vars)
return HttpResponse(data, content_type='application/json')
def tournament_group_stages(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
live_group_stages = list(tournament.live_group_stages())
unique_steps = sorted(set(gs.step for gs in live_group_stages), reverse=True)
return render(request, 'tournaments/group_stages.html', {
'tournament': tournament,
'group_stages': live_group_stages,
'unique_steps': unique_steps,
})
def tournament_broadcasted_group_stages(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcasted_group_stages.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def tournament_live_group_stage_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
# Get all live group stages and filter for the last running step
live_group_stages = [gs.live_group_stages() for gs in tournament.last_group_stage_step()]
gs_dicts = [gs.to_dict() for gs in live_group_stages]
data = json.dumps(gs_dicts)
return HttpResponse(data, content_type='application/json')
def tournament_rankings(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
rankings = tournament.rankings()
return render(request, 'tournaments/rankings.html', {
'tournament': tournament,
'rankings': rankings,
})
def tournament_rankings_json(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
rankings = tournament.rankings()
data = json.dumps(rankings, default=vars)
return HttpResponse(data, content_type='application/json')
def tournament_broadcast_rankings(request, tournament_id):
tournament = get_object_or_404(Tournament, pk=tournament_id)
return render(request, 'tournaments/broadcast/broadcasted_rankings.html', {
'tournament': tournament,
'qr_code_url': qr_code_url(request, tournament_id),
'qr_code_options': qr_code_options(),
})
def players(request):
return render(request, 'tournaments/test.html')
def activate(request, uidb64, token):
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = CustomUser.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, CustomUser.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
next_url = request.GET.get('next', '/')
return redirect(next_url)
else:
return HttpResponse('Le lien est invalide.')
def club_broadcast(request, broadcast_code):
club = get_object_or_404(Club, broadcast_code=broadcast_code)
q_not_deleted = Q(is_deleted=False, event__club=club)
tournaments = Tournament.objects.filter(q_not_deleted).order_by('-start_date')
return render(request, 'tournaments/broadcast/broadcast_club.html', {
'club': club,
'tournaments': tournaments,
})
def club_broadcast_auto(request, broadcast_code):
club = get_object_or_404(Club, broadcast_code=broadcast_code)
q_not_deleted = Q(is_deleted=False, event__club=club)
now = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
recent_time_window = now - timedelta(hours=4)
tournaments = Tournament.objects.filter(
q_not_deleted,
Q(is_private=False), # Exclude private tournaments
(
(
Q(end_date__isnull=True) & # Include ongoing tournaments
(Q(start_date__gte=now - timedelta(days=3)) & Q(start_date__lt=now + timedelta(days=3))) # Include tournaments that are ongoing and start within 3 days
) |
(Q(end_date__isnull=False) & Q(end_date__gte=recent_time_window)) # Include tournaments finished within the last 4 hours
)
)
tournament_ids = [str(tournament.id) for tournament in tournaments]
#print(tournament_ids)
return render(request, 'tournaments/broadcast/broadcasted_auto_event.html', {
'tournament_ids': tournament_ids,
'club_name': club.name,
'qr_code_url': qr_code_url_with_query(request, club.id),
'qr_code_options': qr_code_options(),
})
def download(request):
return render(request, 'tournaments/download.html')
def test_apns(request):
token = DeviceToken.objects.first()
asyncio.run(send_push_notification(token.value, 'hello!'))
return HttpResponse('OK!')
def test_websocket(request):
return render(request, 'tournaments/test_websocket.html')
def terms_of_use(request):
return render(request, 'terms_of_use.html')
import pandas as pd
from .utils.extensions import create_random_filename
@csrf_exempt
def xls_to_csv(request):
if request.method == 'POST':
# Check if the request has a file
if 'file' in request.FILES:
uploaded_file = request.FILES['file']
# Save the uploaded file
directory = 'tmp/csv/'
file_path = os.path.join(directory, uploaded_file.name)
file_name = default_storage.save(file_path, ContentFile(uploaded_file.read()))
# convert to csv and save
data_xls = pd.read_excel(file_name, sheet_name=0, index_col=None)
csv_file_name = create_random_filename('players', 'csv')
output_path = os.path.join(directory, csv_file_name)
data_xls.to_csv(output_path, sep=';', index=False, encoding='utf-8')
# Send the processed file back
with default_storage.open(output_path, 'rb') as file:
response = HttpResponse(file.read(), content_type='application/octet-stream')
response['Content-Disposition'] = f'attachment; filename="players.csv"'
# Clean up: delete both files
default_storage.delete(file_path)
default_storage.delete(output_path)
return response
else:
return HttpResponse("No file was uploaded", status=400)
else:
return HttpResponse("Only POST requests are allowed", status=405)
def simple_form_view(request):
if request.method == 'POST':
# If this is a POST request, we need to process the form data
form = SimpleForm(request.POST)
if form.is_valid():
# Process the data in form.cleaned_data
name = form.cleaned_data['name']
# Do something with the data (e.g., save to the database)
send_email_to_jap_list()
# send_email('laurent@staxriver.com', 'Laurent')
return HttpResponse(f"Hello, {name}!") # Simple response with name
else:
form = SimpleForm()
# print(request.method)
# If this is a GET request, we display an empty form
return render(request, 'tournaments/admin/mail_test.html', {'form': form})
def send_email_to_jap_list():
# Open the CSV file
with open('tournaments/static/misc/jap-test.csv', 'r') as file:
csv_reader = csv.reader(file)
def log_error(message):
with open('email_errors.log', 'a') as log_file:
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
log_file.write(f"{timestamp}: {message}\n")
batch = []
for row in csv_reader:
if len(row) >= 4:
name = row[2]
mail = row[3]
batch.append((mail, name))
if len(batch) == 10:
for email, recipient_name in batch:
try:
send_email(email, recipient_name)
print(f"Name: {recipient_name}, mail: {email}")
except Exception as e:
error_message = f"Error sending email to {email}: {str(e)}"
log_error(error_message)
print(error_message)
batch = []
time.sleep(2)
else:
print(f"Row doesn't have enough elements: {row}")
# Send any remaining emails in the last batch
for email, recipient_name in batch:
try:
send_email(email, recipient_name)
print(f"Name: {recipient_name}, mail: {email}")
except Exception as e:
error_message = f"Error sending email to {email}: {str(e)}"
log_error(error_message)
print(error_message)
def send_email(mail, name):
if name.lower() not in mail.lower():
name = ""
subject = "Tes tournois en toute simplicité avec Padel Club"
body = f"Salut {name} !\n\nJe me permets de t'écrire car je suis JAP2 en région PACA et développeur, et je viens de lancer Padel Club, une app iOS qui facilite enfin l'organisation des tournois.\n\nAvec elle, tu peux convoquer rapidement, simuler et programmer tes structures, diffuser tous les résultats à tous les joueurs, et ce depuis un iPhone.\n\nTu peux l'essayer gratuitement pour découvrir tout son potentiel ! Télécharge l'app ici et teste la dès ton prochain tournoi: https://padelclub.app/download/\n\nJe suis disponible pour échanger avec toi par mail ou téléphone au 06 81 59 81 93 et voir ce que tu en penses.\nÀ bientôt j'espère !\n\nRazmig"
email = EmailMessage(subject, body, to=[mail])
email.send()
def signup(request):
next_url = request.GET.get('next', '/') # Get the 'next' parameter from the request
print('next_url', next_url)
if request.method == 'POST':
form = SimpleCustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = False # Deactivate account until email is verified
user.save()
# Send verification email
send_verification_email(request, user, next_url)
messages.success(request, "Votre compte a été créé ! Veuillez vérifier votre e-mail pour confirmer votre compte.")
return redirect(next_url) # Redirect directly to the 'next' URL
else:
form = SimpleCustomUserCreationForm()
return render(request, 'registration/signup.html', {'form': form})
def send_verification_email(request, user, next_url):
print('next_url', next_url)
current_site = get_current_site(request)
mail_subject = 'Activez votre compte Padel Club !'
# Prepare the email subject and message
message = render_to_string('tournaments/acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
'next': next_url, # Pass next URL to the template
})
email = EmailMessage(mail_subject, message, to=[user.email])
email.send()
@login_required
def profile(request):
user = request.user # Get the currently authenticated user
# Assuming the authenticated user has a `licence_id` attribute
user_licence_id = request.user.licence_id
return render(request, 'registration/profile.html', {
'user_name': user.username
})
def register_tournament(request, tournament_id):
tournament = get_object_or_404(Tournament, id=tournament_id)
registration_successful = False # Flag for registration status
team_form = None
add_player_form = None
if 'user_without_licence' not in request.session:
request.session['user_without_licence'] = False
user_without_licence = request.session['user_without_licence']
# Process forms
if request.method == 'POST':
team_form = TournamentRegistrationForm(request.POST)
# Check if the add player form is submitted
add_player_form = AddPlayerForm(request.POST)
if 'add_player' in request.POST and add_player_form.is_valid():
player_data = add_player_form.cleaned_data
# Validate the license ID before adding the player
licence_id = player_data['licence_id'].upper()
# Instantiate your custom validator and validate the license ID
validator = LicenseValidator(licence_id)
if validator.validate_license() is False and tournament.license_is_required is True:
messages.error(request, f"Le numéro de licence est invalide, la lettre ne correspond pas. {validator.computed_license_key}")
return render(request, 'register_tournament.html', {
'team_form': team_form,
'add_player_form': add_player_form,
'tournament': tournament,
'registration_successful': registration_successful,
'current_players': request.session['team_registration'],
'user_without_licence': user_without_licence
})
# Check if the player with the same licence_id already exists in the session
existing_players = [player['licence_id'] for player in request.session['team_registration']]
if validator.validate_license() and licence_id in existing_players:
messages.error(request, "Ce joueur est déjà dans l'équipe.")
return render(request, 'register_tournament.html', {
'team_form': team_form,
'add_player_form': add_player_form,
'tournament': tournament,
'registration_successful': registration_successful,
'current_players': request.session['team_registration'],
'user_without_licence': user_without_licence
})
else:
# Check if a PlayerRegistration with the same licence_id already exists in the database
stripped_license = validator.stripped_license
if validator.validate_license() and validate_license_id(stripped_license, tournament) and tournament.license_is_required is True:
messages.error(request, "Un joueur avec ce numéro de licence est déjà inscrit dans une équipe.")
return render(request, 'register_tournament.html', {
'team_form': team_form,
'add_player_form': add_player_form,
'tournament': tournament,
'registration_successful': registration_successful,
'current_players': request.session['team_registration'],
'user_without_licence': user_without_licence
})
elif add_player_form.names_is_valid():
if player_data.get('rank', None) is None:
player_data['rank'] = request.session.get('last_rank', 0)
player_data['is_woman'] = request.session.get('is_woman', False)
request.session['team_registration'].append(player_data)
if request.user.is_authenticated and request.user.licence_id is None:
request.session['user_without_licence'] = False
request.user.licence_id = validator.computed_licence_id
request.user.save()
request.session.modified = True # Ensure session is updated
add_player_form = AddPlayerForm()
else:
if add_player_form.first_tournament is False:
# Retrieve player names from the CSV file
data, found = get_player_name_from_csv(tournament.federal_category, licence_id)
if found and data:
player_data['first_name'] = data['first_name']
player_data['last_name'] = data['last_name']
player_data['rank'] = data['rank']
player_data['is_woman'] = data['is_woman']
# If validation passes, add the player to the session without clearing previous ones
request.session['team_registration'].append(player_data)
request.session.modified = True # Ensure session is updated
add_player_form = AddPlayerForm()
else:
if data:
request.session['last_rank'] = data['rank']
request.session['is_woman'] = data['is_woman']
request.session.modified = True # Ensure session is updated
add_player_form.first_tournament = True
# Check if the team registration form is valid and finalize the registration
elif 'register_team' in request.POST and team_form.is_valid():
registration_date = timezone.now().replace(microsecond=0)
team_registration = TeamRegistration.objects.create(
tournament=tournament,
registration_date=registration_date
)
stripped_license = None
if request.user.is_authenticated and request.user.licence_id is not None:
stripped_license = LicenseValidator(request.user.licence_id).stripped_license
# Create PlayerRegistration objects for each player in the session
for player_data in request.session['team_registration']:
is_captain = False
player_licence_id = player_data['licence_id']
if player_licence_id is not None and stripped_license is not None:
if player_licence_id.startswith(stripped_license):
is_captain = True
is_woman = player_data.get('is_woman', False)
rank = player_data.get('rank', 0)
computed_rank = None
sex = PlayerSexType.MALE
if is_woman is None:
computed_rank = rank
else:
computed_rank = rank
is_woman = player_data.get('is_woman', False) == True
if is_woman:
sex = PlayerSexType.FEMALE
if tournament.federal_category == FederalCategory.MEN and is_woman:
computed_rank = str(int(computed_rank) + FederalCategory.female_in_male_assimilation_addition(int(rank)))
player_registration = PlayerRegistration.objects.create(
team_registration=team_registration,
captain=is_captain,
source=PlayerDataSource.ONLINE_REGISTRATION,
first_name=player_data.get('first_name', None),
last_name=player_data.get('last_name', None),
points=player_data.get('points', None),
assimilation=player_data.get('assimilation', None),
tournament_played=player_data.get('tournament_count', None),
ligue_name=player_data.get('ligue_name', None),
club_name=player_data.get('club_name', None),
birthdate=player_data.get('birth_year', None),
sex = sex,
rank = rank,
computed_rank = computed_rank,
licence_id=player_data['licence_id'],
email = team_form.cleaned_data['email'],
phone_number = team_form.cleaned_data['mobile_number']
)
team_registration.set_weight()
request.session['team_registration'] = []
registration_successful = True
else:
add_player_form = AddPlayerForm()
request.session['team_registration'] = []
initial_data = {}
player_data = {}
# Add the authenticated user to the session as the first player if not already added
if request.user.is_authenticated:
user_licence_id = request.user.licence_id
initial_data = {
'email': request.user.email,
'phone': request.user.phone,
}
if user_licence_id is not None:
validator = LicenseValidator(user_licence_id)
existing_players = [player['licence_id'] for player in request.session['team_registration']]
if user_licence_id not in existing_players:
# Add the authenticated user as the first player in the session
player_data = {
'first_name': request.user.first_name,
'last_name': request.user.last_name.upper(),
'email': request.user.email,
'phone': request.user.phone,
'licence_id': validator.computed_licence_id
}
data, found = get_player_name_from_csv(tournament.federal_category, user_licence_id)
if found and data:
player_data['rank'] = data['rank']
player_data['points'] = data.get('points', None)
player_data['assimilation'] = data.get('assimilation', None)
player_data['tournament_count'] = data.get('tournament_count', None)
player_data['ligue_name'] = data.get('ligue_name', None)
player_data['club_name'] = data.get('club_name', None)
player_data['birth_year'] = data.get('birth_year', None)
request.session['team_registration'].insert(0, player_data) # Add them as the first player
request.session.modified = True # Ensure session is updated
else:
player_data = {
'first_name': request.user.first_name,
'last_name': request.user.last_name.upper(),
}
add_player_form = AddPlayerForm(initial=player_data)
request.session['user_without_licence'] = True
request.session.modified = True # Ensure session is updated
user_without_licence = True
team_form = TournamentRegistrationForm(initial=initial_data)
return render(request, 'register_tournament.html', {
'team_form': team_form,
'add_player_form': add_player_form,
'tournament': tournament,
'registration_successful': registration_successful,
'current_players': request.session['team_registration'],
'user_without_licence': request.session['user_without_licence']
})
@login_required
def unregister_tournament(request, tournament_id):
user_licence_id = request.user.licence_id
player_registration = PlayerRegistration.objects.filter(
licence_id__startswith=user_licence_id,
team_registration__tournament_id=tournament_id
).first() # Get the first match, if any
if player_registration:
team_registration = player_registration.team_registration # Get the related TeamRegistration
team_registration.delete() # Delete the team registration
request.session['team_registration'] = []
return redirect('tournament-info', tournament_id=tournament_id)
def validate_license_id(licence_id, tournament):
teams = TeamRegistration.objects.filter(tournament=tournament)
# Check if any player in any team in the tournament already has this licence_id
# Normalize the licence ID before querying
# Loop through each team and check if any of its players has the same licence_id
for team in teams:
for player in team.playerregistration_set.all():
if player.licence_id is not None and player.licence_id.startswith(licence_id):
return True
# If all checks pass, return True (you can add further logic here if needed)
return False
class CustomPasswordResetConfirmView(PasswordResetConfirmView):
template_name = 'registration/password_reset_confirm.html' # Custom template
def get_context_data(self, **kwargs):
"""
Modify the context to provide custom data to the template.
"""
context = super().get_context_data(**kwargs)
context['custom_message'] = "Veuillez entrer un nouveau mot de passe."
return context
def form_valid(self, form):
"""
Custom behavior when the password reset form is valid.
"""
# Call the parent method to save the new password
response = super().form_valid(form)
# Additional actions (e.g., logging or sending notifications) can be added here
# You can add custom logic after password reset
return response
def get_user(self, uidb64):
"""
Override this method to decode the uid and return the corresponding user.
"""
try:
uid = urlsafe_base64_decode(uidb64).decode()
user = User.objects.get(pk=uid)
return user
except (TypeError, ValueError, User.DoesNotExist):
raise Http404("User not found")
@login_required
def my_tournaments(request):
user = request.user # Get the currently authenticated user
# Assuming the authenticated user has a `licence_id` attribute
user_licence_id = request.user.licence_id
# Check if licence_id is None
if user_licence_id is None:
tournaments = Tournament.objects.none() # Return an empty queryset
else:
validator = LicenseValidator(user_licence_id)
stripped_license = validator.stripped_license
# Filter tournaments where the authenticated user's licence_id starts with the given value
tournaments = Tournament.objects.filter(
teamregistration__playerregistration__licence_id__startswith=stripped_license
).distinct().order_by('-start_date')
# Current time
current_time = timezone.now()
# Separate tournaments into categories
upcoming_tournaments = tournaments.filter(start_date__gt=current_time)
running_tournaments = tournaments.filter(start_date__lte=current_time, end_date=None)
ended_tournaments = tournaments.filter(end_date__isnull=False)
return render(request, 'registration/my_tournaments.html', {
'tournaments': tournaments,
'upcoming_tournaments': upcoming_tournaments,
'running_tournaments': running_tournaments,
'ended_tournaments': ended_tournaments,
'user_name': user.username
})
from django.contrib.auth.forms import PasswordChangeForm
class ProfileUpdateView(UpdateView):
model = CustomUser
form_class = ProfileUpdateForm
template_name = 'profile.html'
success_url = reverse_lazy('profile')
def get_object(self, queryset=None):
return self.request.user
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['password_change_form'] = PasswordChangeForm(user=self.request.user)
return context