- Certificate model: serial_number (unique), status (pending/rendering/completed/failed),
pdf_path, pdf_hash (SHA-256), verification_url, render_attempts, training_record FK
- renderer.py: LaTeX template → pdflatex subprocess → PDF; _escape_latex for XSS safety;
compute_pdf_hash for immutable verification metadata
- services.py: issue_certificate() generates serial, creates record, enqueues Celery task
- tasks.py: render_certificate_task (bind=True, autoretry 3x with 60s backoff);
sets RENDERING → COMPLETED with hash; FAILED with error on all retries exhausted
- API: /certificates/ (own list), /certificates/{id}/ (own detail)
- 15 unit + integration tests: hash consistency, LaTeX escaping, mocked render, retry behavior
Co-Authored-By: Paperclip <noreply@paperclip.ing>
14 lines
373 B
Python
14 lines
373 B
Python
from rest_framework import serializers
|
|
|
|
from .models import Certificate
|
|
|
|
|
|
class CertificateSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Certificate
|
|
fields = [
|
|
"id", "serial_number", "course", "user", "status",
|
|
"issued_at", "pdf_hash", "verification_url", "created_at",
|
|
]
|
|
read_only_fields = fields
|