Ok, this is more or less "present sparse data having two foreign keys in a table, key1 in rows and key2 in columns". Common enough thing to do, I imagine, but with a wee twist.
In Django, I need to make a page with semester score for a group of students. It should look like this:
Cryptography intro | Discrete Math | ...
Chkpt1 Chkpt2 Chkpt3 | Chkpt1 Chkpt2 Chkpt3 | ...
Alice 15 26 47 | 10 20 - | ...
Bob 25 54 73 | 25 54 - | ...
Chuck 33 66 99 | 33 60 - | ...
...
Students in a group all take the same courses, and the school has defined 3 checkpoints during each semester when all instructors report the scores. Some columns may not be filled yet if the instructor has not yet turned in the scores (Chkpt3 in Discrete Math in the example above).
Model for a Grade references Student, Course, and Checkpoint. Checkpoint references Semester. Students reference Group.
Problem is how to pass data to the template. I get data from the DB with
reportgrades = Grade.objects.filter(student__group__id=group_id,
checkpoint__semester=semester)
Then I:
- go create nested dict
gr[studid][courseid][chkptid]in a nested loop, fill it with dashes, loop over
reportgradesto put values into this dict, overwriting dashes where grades exist,no_grade = u'—' grades = {} for student in students: grades[student.id] = {} for course in courses: grades[student.id][course.id] = {} for chkpt in checkpoints: grades[student.id][course.id][chkpt.id] = no_grade for g in reportgrades: grades[g.student.id][g.course.id][g.checkpoint.id] = g.pointscreate custom template tag to extract these,
@register.filter def getitem ( item, param1 ): return item.get(param1)use this inside a 3-nested
forin the template{% for s in students %} <tr> <td>{{ s }}</td> {% for c in courses %} {% for tp in test_periods %} <td>{{ grades| getitem:s.id | getitem:c.id | getitem:tp.id }}</td> {% endfor %} {% endfor %} </tr> {% endfor %}
That's an awful lot to do to get a simple table, is it not? I've considered a linear list of size 3 x NUM_STUDENTS x NUM_COURSES. Not very pretty, either. A better way?