Application de gestion de courses avec génération de dossards avec QRcode et scan des coureurs à l'arrivée.
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.
 
 
 
 
 

90 lines
2.7 KiB

import csv
from django.contrib.auth.decorators import login_required
import io
from django.shortcuts import render
from django.http import HttpResponse
from .forms import DossardForm
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
import qrcode
from PIL import Image
from django.core.files.storage import default_storage
def generate_dossards_pdf(data, rows, cols):
buffer = io.BytesIO()
c = canvas.Canvas(buffer, pagesize=A4)
width, height = A4
margin = 10 * mm
label_w = (width - 2 * margin) / cols
label_h = (height - 2 * margin) / rows
x0, y0 = margin, height - margin - label_h
qr_scale = 0.8 # 80% de la zone pour le QR code
for idx, (nom, classe) in enumerate(data):
col = idx % cols
row = (idx // cols) % rows
page = idx // (rows * cols)
if idx > 0 and row == 0 and col == 0:
c.showPage()
x = x0 + col * label_w
y = y0 - row * label_h
# Dessiner le rectangle de la zone d'étiquette
c.setLineWidth(3)
c.setStrokeColorRGB(0, 0, 0)
c.rect(x, y, label_w, label_h)
# Générer QR code
qr = qrcode.make(f"{nom};{classe}")
qr_img = io.BytesIO()
qr.save(qr_img, format='PNG')
qr_img.seek(0)
qr_pil = Image.open(qr_img)
# Calculer la taille maximale du QR code (carré) dans la zone
qr_size = min(label_w, label_h) * qr_scale
qr_x = x + (label_w - qr_size) / 2
qr_y = y + (label_h - qr_size) / 2
c.drawInlineImage(qr_pil, qr_x, qr_y, qr_size, qr_size)
# Afficher le nom et la classe sous le QR code
c.setFont("Helvetica-Bold", 12)
c.drawCentredString(x + label_w/2, qr_y - 10, nom)
c.setFont("Helvetica", 10)
c.drawCentredString(x + label_w/2, qr_y - 24, classe)
c.save()
buffer.seek(0)
return buffer
@login_required
def dossards_view(request):
error = None
progress = None
pdf_url = None
if request.method == 'POST':
form = DossardForm(request.POST, request.FILES)
if form.is_valid():
csv_file = form.cleaned_data['csv_file']
rows = form.cleaned_data['rows']
cols = form.cleaned_data['cols']
try:
data = []
for line in csv_file.read().decode('utf-8').splitlines():
if line.count(';') == 1:
nom, classe = line.split(';')
data.append((nom.strip(), classe.strip()))
total = len(data)
progress = f"Génération des dossards : 0/{total}..."
buffer = generate_dossards_pdf(data, rows, cols)
response = HttpResponse(buffer, content_type='application/pdf')
response['Content-Disposition'] = f'attachment; filename="dossards_{rows}x{cols}.pdf"'
return response
except Exception as e:
error = str(e)
else:
error = "Formulaire invalide."
else:
form = DossardForm()
return render(request, 'dossards.html', {
'form': form,
'error': error,
'progress': progress,
'pdf_url': pdf_url
})