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
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 |
|
})
|
|
|