Complete guide to template variables, data structures, and implementation for generating academic reports.
Your backend must provide these root objects in the rendering context.
{
"school": {...},
"student": {...},
"session": {...},
"term": {...},
"subjects": [...],
"assessment_fields": [...],
"summary": {...},
"psychomotor": {...},
"affective": {...},
"custom_ratings": {...},
"get_remark": function
}
school.name
String
school.logo
URL/Base64
school.address
String
school.phone
String
school.email
String
student.name
String
student.reg_no
String
student.class
String
student.age
String (Pre-calculated)
student.passport_photo
URL
context = {
"school": {
"name": "SCHOOL OF EXCELLENCE",
"logo": "https://example.com/logo.png",
"address": "123 Education Street",
"phone": "+234 801 234 5678",
"email": "info@schoolexcellence.edu",
"website": "www.schoolexcellence.edu",
"motto": "Knowledge is Power"
},
"student": {
"name": "John Doe",
"reg_no": "REG-2024-001",
"class": "JSS 3A",
"gender": "Male",
"dob": "15/03/2008",
"age": 15,
"passport_photo": "https://ui-avatars.com/api/?name=John+Doe"
},
"session": {"id": 1, "name": "2023/2024"},
"term": {"id": 1, "name": "First Term"},
"subjects": [
{
"name": "Mathematics",
"code": "MATH",
"total": 90.0,
"grade": "A",
"remark": "Excellent",
"position": "1st",
"assessment_scores": {
"quiz": 15,
"assignment": 13,
"midterm": 30,
"project": 17
}
}
],
"assessment_fields": [
{
"display_name": "Quiz",
"field_code": "quiz",
"max_score": 20.0,
"weight": 0.15,
"field_type": "test",
"is_compulsory": True
}
],
"summary": {
"total_score": 540.0,
"average_score": 85.5,
"overall_grade": "A",
"class_position": "3rd",
"total_subjects": 8,
"report_date": "25 January, 2024",
"teacher_comment": "Excellent performance.",
"principal_comment": "Keep it up."
},
"psychomotor": {
"Handwriting": "Good",
"Sports": "Excellent"
},
"affective": {
"Punctuality": "Very Good",
"Neatness": "Good"
},
"get_remark": get_remark_function
}
def get_remark(grade):
remarks = {
"A": "Excellent",
"B": "Very Good",
"C": "Good",
"D": "Pass",
"F": "Fail"
}
return remarks.get(grade, "N/A")
def calculate_age(dob):
# Must be pre-calculated in backend
today = datetime.today()
age = today.year - dob.year
if today.month < dob.month or (today.month == dob.month and today.day < dob.day):
age -= 1
return f"{age} years"
get_remark function must be injected
{% if assessment_fields and assessment_fields|length > 0 %}
<!-- Show dynamic assessment columns -->
{% else %}
<!-- Legacy CA/Exam fallback -->
{% endif %}
{% if psychomotor or affective %}
<!-- Show behavioral assessments -->
{% endif %}
{% for subject in subjects %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ subject.name }}</td>
<td>{{ subject.total }}</td>
<td>{{ subject.grade }}</td>
<td>{{ subject.remark }}</td>
</tr>
{% endfor %}
assessment_fields is empty, template uses CA/Exam fallbackca_score and exam_scoreassessment_scores keys must match field_codeThe template is designed to handle missing data gracefully:
Dynamic assessment fields allow custom scoring categories:
assessment_fields = [
{
"display_name": "Classwork",
"field_code": "classwork",
"max_score": 10.0,
"weight": 0.10,
"field_type": "activity"
},
{
"display_name": "Project",
"field_code": "project",
"max_score": 30.0,
"weight": 0.30,
"field_type": "assignment"
}
]
Each subject must have matching assessment_scores with these field codes.
Yes! Use the custom_ratings object for school-specific traits:
custom_ratings = {
"Leadership Skills": "Excellent",
"Team Collaboration": "Very Good",
"Creativity": "Good",
"Problem Solving": "Excellent"
}
These will automatically appear in the behavioral assessment section.
For PDF generation, ensure:
The template is optimized for performance:
Grade calculations should be done in the backend:
def calculate_grade(score):
if score >= 75: return "A"
elif score >= 70: return "AB"
elif score >= 65: return "B"
elif score >= 60: return "BC"
elif score >= 55: return "C"
elif score >= 50: return "CD"
elif score >= 45: return "D"
elif score >= 40: return "E"
else: return "F"
# Apply to each subject
for subject in subjects:
subject['grade'] = calculate_grade(subject['total'])
subject['remark'] = get_remark(subject['grade'])
The template only displays pre-calculated grades.
subjects list is non-empty
get_remark function is injected
assessment_scores keys match field_code
Our team can help you integrate this template system into your application.
We offer complete integration services including backend development, template customization, and PDF generation.
Contact Sales Team