Browse Source

Nettoyage + commentaires

master
scayac 2 months ago
parent
commit
8a1679c568
  1. 253
      main/views.py

253
main/views.py

@ -1,146 +1,179 @@ @@ -1,146 +1,179 @@
from django.http import JsonResponse
from django.views.decorators.http import require_GET
# Standard library
import csv
import io
from datetime import timedelta
from django.http import HttpResponse
# Django
from django.db import models
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from django.views.decorators.http import require_GET
# Third party
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
import qrcode
from PIL import Image
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
# Local
from .models import Course, Arrivee, Coureur
from django.db import models
from .forms import CourseForm, ScanForm, DossardForm
import qrcode
from PIL import Image
# =====================================
# Fonctions utilitaires
# =====================================
def seconds_to_hms(delta: timedelta) -> str:
if delta is None:
return ''
total = int(delta.total_seconds())
hours = total // 3600
minutes = (total % 3600) // 60
seconds = total % 60
return f"{hours}h{minutes:02d}m{seconds:02d}s"
"""Convertit une durée timedelta en chaîne formatée HhMMmSSs"""
if delta is None:
return ''
total = int(delta.total_seconds())
hours = total // 3600
minutes = (total % 3600) // 60
seconds = total % 60
return f"{hours}h{minutes:02d}m{seconds:02d}s"
@login_required
@require_GET
def coureur_autocomplete(request):
q = request.GET.get('q', '').strip()
results = []
if len(q) >= 2:
# Recherche sur nom, prénom, classe, dossard (id)
qs = Coureur.objects.filter(
models.Q(nom__icontains=q) |
models.Q(prenom__icontains=q) |
models.Q(classe__icontains=q) |
models.Q(id__icontains=q)
).order_by('nom', 'prenom')[:10]
for c in qs:
label = f"{c.nom} {c.prenom} ({c.classe}) [dossard: {c.id}]"
results.append({'id': c.id, 'label': label})
return JsonResponse(results, safe=False)
"""Endpoint AJAX pour l'autocomplétion des coureurs.
Recherche sur nom, prénom, classe et dossard.
Retourne les 10 premiers résultats au format {id, label}."""
q = request.GET.get('q', '').strip()
results = []
if len(q) >= 2:
qs = Coureur.objects.filter(
models.Q(nom__icontains=q) |
models.Q(prenom__icontains=q) |
models.Q(classe__icontains=q) |
models.Q(id__icontains=q)
).order_by('nom', 'prenom')[:10]
for c in qs:
label = f"{c.nom} {c.prenom} ({c.classe}) [dossard: {c.id}]"
results.append({'id': c.id, 'label': label})
return JsonResponse(results, safe=False)
# =====================================
# Vues principales
# =====================================
@login_required
def main_view(request):
courses = Course.objects.filter(owner=request.user)
if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest':
from django.http import JsonResponse
nom = request.POST.get('nom')
date = timezone.localdate()
if not nom:
return JsonResponse({'success': False, 'error': "Le nom de la course est requis."})
if Course.objects.filter(nom=nom, date=date).exists():
return JsonResponse({'success': False, 'error': "Une course avec ce nom existe d\u00e9j\u00e0 aujourd'hui."})
course = Course.objects.create(nom=nom, date=date, owner=request.user)
return JsonResponse({'success': True, 'course_id': course.id})
form = CourseForm()
return render(request, 'main.html', {
'title': 'Accueil',
'courses': courses,
'form': form,
'now': timezone.localdate()
})
"""Page d'accueil listant les courses de l'utilisateur.
Permet aussi la création AJAX de nouvelles courses."""
courses = Course.objects.filter(owner=request.user)
if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest':
nom = request.POST.get('nom')
date = timezone.localdate()
if not nom:
return JsonResponse({'success': False, 'error': "Le nom de la course est requis."})
if Course.objects.filter(nom=nom, date=date).exists():
return JsonResponse({'success': False, 'error': "Une course avec ce nom existe déjà aujourd'hui."})
course = Course.objects.create(nom=nom, date=date, owner=request.user)
return JsonResponse({'success': True, 'course_id': course.id})
form = CourseForm()
return render(request, 'main.html', {
'title': 'Accueil',
'courses': courses,
'form': form,
'now': timezone.localdate()
})
# =====================================
# Vues d'export
# =====================================
@login_required
def export_csv(request, course_id):
course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.csv"'
writer = csv.writer(response)
writer.writerow(['Rang', 'Nom', 'Classe', 'Temps'])
import json
rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json:
try:
rows = json.loads(rows_json)
for row in rows:
writer.writerow(row)
except Exception:
pass
else:
arrivees = course.arrivees.select_related('coureur').order_by('rang')
for a in arrivees:
writer.writerow([a.rang, a.coureur.nom, a.coureur.classe, str(a.temps)])
return response
"""Export des résultats d'une course en CSV.
Supporte soit l'export direct depuis la base, soit l'export des lignes filtrées envoyées en POST."""
course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.csv"'
writer = csv.writer(response)
writer.writerow(['Rang', 'Nom', 'Classe', 'Temps'])
import json
rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json:
try:
rows = json.loads(rows_json)
for row in rows:
writer.writerow(row)
except Exception:
pass
else:
arrivees = course.arrivees.select_related('coureur').order_by('rang')
for a in arrivees:
writer.writerow([a.rang, a.coureur.nom, a.coureur.classe, str(a.temps)])
return response
@login_required
def export_pdf(request, course_id):
course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.pdf"'
p = canvas.Canvas(response, pagesize=A4)
width, height = A4
"""Export des résultats d'une course en PDF.
Supporte soit l'export direct depuis la base, soit l'export des lignes filtrées envoyées en POST."""
course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.pdf"'
y = height - 50
p.setFont("Helvetica-Bold", 16)
p.drawString(50, y, f"R\u00e9sultats - {course.nom} ({course.date})")
y -= 40
p.setFont("Helvetica", 12)
p.drawString(50, y, "Rang")
p.drawString(100, y, "Nom")
p.drawString(300, y, "Classe")
p.drawString(400, y, "Temps")
y -= 20
import json
rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json:
try:
rows = json.loads(rows_json)
for row in rows:
p.drawString(50, y, str(row[0]))
p.drawString(100, y, str(row[1]))
p.drawString(300, y, str(row[2]))
p.drawString(400, y, str(row[3]))
y -= 20
if y < 50:
p.showPage()
y = height - 50
except Exception:
pass
else:
arrivees = course.arrivees.select_related('coureur').order_by('rang')
for a in arrivees:
p.drawString(50, y, str(a.rang))
p.drawString(100, y, a.coureur.nom)
p.drawString(300, y, a.coureur.classe)
p.drawString(400, y, str(a.temps))
y -= 20
if y < 50:
p.showPage()
y = height - 50
p.save()
return response
# Configuration du document PDF
p = canvas.Canvas(response, pagesize=A4)
width, height = A4
# En-tête
y = height - 50
p.setFont("Helvetica-Bold", 16)
p.drawString(50, y, f"Résultats - {course.nom} ({course.date})")
# En-tête du tableau
y -= 40
p.setFont("Helvetica", 12)
p.drawString(50, y, "Rang")
p.drawString(100, y, "Nom")
p.drawString(300, y, "Classe")
p.drawString(400, y, "Temps")
y -= 20
# Contenu : soit les lignes filtrées, soit toutes les arrivées
import json
rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json:
try:
rows = json.loads(rows_json)
for row in rows:
p.drawString(50, y, str(row[0]))
p.drawString(100, y, str(row[1]))
p.drawString(300, y, str(row[2]))
p.drawString(400, y, str(row[3]))
y -= 20
# Nouvelle page si nécessaire
if y < 50:
p.showPage()
y = height - 50
except Exception:
pass
else:
arrivees = course.arrivees.select_related('coureur').order_by('rang')
for a in arrivees:
p.drawString(50, y, str(a.rang))
p.drawString(100, y, a.coureur.nom)
p.drawString(300, y, a.coureur.classe)
p.drawString(400, y, str(a.temps))
y -= 20
# Nouvelle page si nécessaire
if y < 50:
p.showPage()
y = height - 50
p.save()
return response
@login_required
def course_detail_view(request, course_id):

Loading…
Cancel
Save