Browse Source

Nettoyage + commentaires

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

55
main/views.py

@ -1,29 +1,35 @@
from django.http import JsonResponse # Standard library
from django.views.decorators.http import require_GET
import csv import csv
import io import io
from datetime import timedelta 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.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.utils import timezone from django.utils import timezone
from django.views.decorators.http import require_GET
# Third party
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4 from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm from reportlab.lib.units import mm
import qrcode
from PIL import Image
from channels.layers import get_channel_layer from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync from asgiref.sync import async_to_sync
# Local
from .models import Course, Arrivee, Coureur from .models import Course, Arrivee, Coureur
from django.db import models
from .forms import CourseForm, ScanForm, DossardForm from .forms import CourseForm, ScanForm, DossardForm
import qrcode # =====================================
from PIL import Image # Fonctions utilitaires
# =====================================
def seconds_to_hms(delta: timedelta) -> str: def seconds_to_hms(delta: timedelta) -> str:
"""Convertit une durée timedelta en chaîne formatée HhMMmSSs"""
if delta is None: if delta is None:
return '' return ''
total = int(delta.total_seconds()) total = int(delta.total_seconds())
@ -35,10 +41,12 @@ def seconds_to_hms(delta: timedelta) -> str:
@login_required @login_required
@require_GET @require_GET
def coureur_autocomplete(request): def coureur_autocomplete(request):
"""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() q = request.GET.get('q', '').strip()
results = [] results = []
if len(q) >= 2: if len(q) >= 2:
# Recherche sur nom, prénom, classe, dossard (id)
qs = Coureur.objects.filter( qs = Coureur.objects.filter(
models.Q(nom__icontains=q) | models.Q(nom__icontains=q) |
models.Q(prenom__icontains=q) | models.Q(prenom__icontains=q) |
@ -50,19 +58,26 @@ def coureur_autocomplete(request):
results.append({'id': c.id, 'label': label}) results.append({'id': c.id, 'label': label})
return JsonResponse(results, safe=False) return JsonResponse(results, safe=False)
# =====================================
# Vues principales
# =====================================
@login_required @login_required
def main_view(request): def main_view(request):
"""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) courses = Course.objects.filter(owner=request.user)
if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest': if request.method == 'POST' and request.headers.get('x-requested-with') == 'XMLHttpRequest':
from django.http import JsonResponse
nom = request.POST.get('nom') nom = request.POST.get('nom')
date = timezone.localdate() date = timezone.localdate()
if not nom: if not nom:
return JsonResponse({'success': False, 'error': "Le nom de la course est requis."}) return JsonResponse({'success': False, 'error': "Le nom de la course est requis."})
if Course.objects.filter(nom=nom, date=date).exists(): 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."}) 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) course = Course.objects.create(nom=nom, date=date, owner=request.user)
return JsonResponse({'success': True, 'course_id': course.id}) return JsonResponse({'success': True, 'course_id': course.id})
form = CourseForm() form = CourseForm()
return render(request, 'main.html', { return render(request, 'main.html', {
'title': 'Accueil', 'title': 'Accueil',
@ -71,13 +86,20 @@ def main_view(request):
'now': timezone.localdate() 'now': timezone.localdate()
}) })
# =====================================
# Vues d'export
# =====================================
@login_required @login_required
def export_csv(request, course_id): def export_csv(request, course_id):
"""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) course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='text/csv') response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.csv"' response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.csv"'
writer = csv.writer(response) writer = csv.writer(response)
writer.writerow(['Rang', 'Nom', 'Classe', 'Temps']) writer.writerow(['Rang', 'Nom', 'Classe', 'Temps'])
import json import json
rows_json = request.POST.get('rows') rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json: if request.method == "POST" and rows_json:
@ -95,16 +117,22 @@ def export_csv(request, course_id):
@login_required @login_required
def export_pdf(request, course_id): def export_pdf(request, course_id):
"""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) course = get_object_or_404(Course, id=course_id, owner=request.user)
response = HttpResponse(content_type='application/pdf') response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.pdf"' response['Content-Disposition'] = f'attachment; filename="course_{course_id}_resultats.pdf"'
# Configuration du document PDF
p = canvas.Canvas(response, pagesize=A4) p = canvas.Canvas(response, pagesize=A4)
width, height = A4 width, height = A4
# En-tête
y = height - 50 y = height - 50
p.setFont("Helvetica-Bold", 16) p.setFont("Helvetica-Bold", 16)
p.drawString(50, y, f"R\u00e9sultats - {course.nom} ({course.date})") p.drawString(50, y, f"Résultats - {course.nom} ({course.date})")
# En-tête du tableau
y -= 40 y -= 40
p.setFont("Helvetica", 12) p.setFont("Helvetica", 12)
p.drawString(50, y, "Rang") p.drawString(50, y, "Rang")
@ -112,6 +140,8 @@ def export_pdf(request, course_id):
p.drawString(300, y, "Classe") p.drawString(300, y, "Classe")
p.drawString(400, y, "Temps") p.drawString(400, y, "Temps")
y -= 20 y -= 20
# Contenu : soit les lignes filtrées, soit toutes les arrivées
import json import json
rows_json = request.POST.get('rows') rows_json = request.POST.get('rows')
if request.method == "POST" and rows_json: if request.method == "POST" and rows_json:
@ -123,6 +153,7 @@ def export_pdf(request, course_id):
p.drawString(300, y, str(row[2])) p.drawString(300, y, str(row[2]))
p.drawString(400, y, str(row[3])) p.drawString(400, y, str(row[3]))
y -= 20 y -= 20
# Nouvelle page si nécessaire
if y < 50: if y < 50:
p.showPage() p.showPage()
y = height - 50 y = height - 50
@ -136,9 +167,11 @@ def export_pdf(request, course_id):
p.drawString(300, y, a.coureur.classe) p.drawString(300, y, a.coureur.classe)
p.drawString(400, y, str(a.temps)) p.drawString(400, y, str(a.temps))
y -= 20 y -= 20
# Nouvelle page si nécessaire
if y < 50: if y < 50:
p.showPage() p.showPage()
y = height - 50 y = height - 50
p.save() p.save()
return response return response

Loading…
Cancel
Save