Django DB数据到HTML表

时间:2012-11-30 11:09:22

标签: django templates

好吧,这或多或少是“当前稀疏数据在表中有两个外键,行中的key1和列中的key2”。我想,常见的事情要做,但是有点麻烦。

在Django中,我需要为一组学生制作一个学期分数的页面。它应该是这样的:

          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     -    | ...     
...

小组中的学生都参加相同的课程,学校在每个学期都定义了3个检查点,所有教师都会报告分数。如果教师尚未输入分数,则某些列可能尚未填充(上例中的离散数学中的Chkpt3)。

成绩模型引用学生,课程和检查点。检查点参考学期。学生参考小组。

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

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

然后我:

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

    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. 在模板

    中的3嵌套for内使用此功能
    {% 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 %}
    
  5. 要获得一张简单的桌子,这是一件非常糟糕的事情,不是吗?我考虑过一个大小为3 x NUM_STUDENTS x NUM_COURSES的线性列表。也不是很漂亮。一个更好的方法?

1 个答案:

答案 0 :(得分: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,所以如果我投入了一个不起作用的功能,我会道歉,但它应该没问题。