10. Les documents PDF
Un emprunteur repart avec un reçu. Le module fournit le gabarit ; le noyau fait le reste.
Un fichier suffit
Déposez reports/library_loan.html. Le nom porte tout : <modèle>.html est le rapport par
défaut du modèle, <modèle>.<nom>.html en est un autre, nommé.
{% extends "kewos:document" %}{% block body %}<h1>{{ t("library_loan.receipt.title") }}</h1>
<table class="kws-table"> <tbody> <tr><th>{{ t("library_loan.member_id") }}</th><td>{{ record.member_id }}</td></tr> <tr><th>{{ t("library_loan.copy_id") }}</th><td>{{ record.copy_id }}</td></tr> <tr><th>{{ t("library_loan.taken_on") }}</th><td>{{ record.taken_on }}</td></tr> <tr><th>{{ t("library_loan.due_on") }}</th><td><strong>{{ record.due_on }}</strong></td></tr> <tr><th>{{ t("library_loan.state") }}</th> <td>{{ t("library_loan.state." ~ record.state) }}</td></tr> </tbody></table>
<p class="kws-muted">{{ t("library_loan.receipt.note") }}</p>{% endblock %}Et une ligne dans le point d’entrée du module :
from kewos.pdf import register_reports_from_dir
register_reports_from_dir(_MODULE_DIR / "reports")Ce que ça donne

L’en-tête, le logo, le pied de page et les couleurs viennent du thème de document de la
société. Vous n’avez écrit ni l’un ni les autres : {% extends "kewos:document" %} les apporte,
et un client qui change son logo change tous ses documents d’un coup.
Le bouton d’impression apparaît sur l’écran du modèle, sans rien déclarer de plus.
Le contexte : ce que le gabarit reçoit
Un rapport qui n’a pas besoin de code Python reçoit un contexte construit génériquement :
| Dans le gabarit | Ce que vous obtenez |
|---|---|
record.<champ> | La valeur, mise en chaîne. |
record.<relation> | Le libellé de l’enregistrement visé. |
record.<enfants> | La liste des enfants, en dictionnaires. |
t("clé") | La traduction, dans la langue du document. |
Quand le générique ne suffit pas
Enregistrez le rapport vous-même, avec un constructeur de contexte :
from kewos.pdf import register_model_report
def _receipt_context(session, classes, record_id): """Everything the receipt needs, including what is two hops away.""" loan = session.get(classes["library_loan"], record_id) return { "record": loan, "title": loan.copy_id.title_id.name, "member_card": loan.member_id.card_number, }
register_model_report( "library_loan", code="library_loan", title="Loan receipt", body_template=TEMPLATE, build_context=_receipt_context,)Un piège d’exploitation, corrigé
Et ensuite
Réagir : agir tout seul, tous les matins.