0

好的,这或多或少是“在表中存在具有两个外键的稀疏数据,行中的 key1 和列中的 key2”。我想,这很常见,但有点扭曲。

在 Django 中,我需要为一组学生制作一个包含学期分数的页面。它应该如下所示:

          密码学介绍 | 离散数学 | ...
         Chkpt1 Chkpt2 Chkpt3 | Chkpt1 Chkpt2 Chkpt3 | ...
爱丽丝 15 26 47 | 10 20 - | ...
鲍勃 25 54 73 | 25 54 - | ...  
查克 33 66 99 | 33 60 - | ...     
...

一个小组的学生都修相同的课程,学校规定了每学期3个考点,由所有教师报告分数。如果教师尚未上交分数(上例中离散数学中的 Chkpt3),则某些列可能尚未填写。

成绩参考学生、课程和检查点的模型。检查点参考学期。学生参考组。

问题是如何将数据传递给模板。我从数据库中获取数据

reportgrades = Grade.objects.filter(student__group__id=group_id, 
                                    checkpoint__semester=semester)

然后我:

  1. 在嵌套循环中创建嵌套字典gr[studid][courseid][chkptid],用破折号填充它,
  2. 循环reportgrades将值放入此字典中,覆盖存在成绩的破折号,

    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.points
    
  3. 创建自定义模板标签来提取这些,

    @register.filter
    def getitem ( item, param1 ):
        return item.get(param1)
    
  4. for在模板中的 3 嵌套中使用它

    {% 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 %}
    

要获得一张简单的桌子,要做很多事情,不是吗?我考虑了一个大小为 3 x NUM_STUDENTS x NUM_COURSES 的线性列表。也不是很漂亮。更好的方法?

4

1 回答 1

1

正如 RickyA 建议的那样,让您的模板代码尽可能简单。而是在您的视图中进行复杂的数据转换。

由于您在顶部和侧面都有标题,因此我会将它们存储在他们自己的列表中。然后我会将实际数据存储在列表列表中。例如,在您的视图代码中:

student = Student.objects.all()
context['classes'] = [class.name for class in Class.objects.all()]
context['checkPoints'] = range(1, 4)
context['data'] = ... 

(code to flatten checkpoints for each students in to flat list, 
then make list of these lists, don't forget to add the student 
name as the first item in each row)

在您的模板中,您可以执行类似的操作

<table>
<thead>
<tr>
<th></th>
{% for class in classes %}
<th colspan="3">{{ class }}</th>
{% endfor %}
</tr>
<!-- something similar for checkpoints -->
</thead>
<tbody>
{% for row in data %}
<tr>
{% for item in row %}
{% if not forloop.counter0 %}
<th>{{ item }}</th>
{% else %}
<td>{{ item }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>

我认为这是有效的 Django 模板代码。我最近一直在使用 Jinja2,所以如果我添加了一个不起作用的功能,我深表歉意,但应该没问题。

于 2012-11-30T12:01:54.273 回答