我正在Django构建一个简单的学校注册应用程序,并且正在努力弄清楚如何创建报告。我认为这是数据的转移,但这可能不是我想要做的事情。广泛的研究和玩熊猫,图表等没有得到任何答案,所以我希望你能提供帮助。
class SemesterPeriod(models.Model):
name = models.CharField(max_length=50)
class Schedule(models.Model):
semester = text
course = Foreign Key
semester_period = models.ForeignKey(SemesterPeriod)
class Student(models.Model):
first_name = models.CharField(max_length=50)
class StudentEnroll(models.Model):
schedule = ForeignKey('Schedule')
student = ForeignKey('Student')
两名学生的数据可能如此
SemesterPeriod
1st_Period
2nd_Period
3rd_Period
Schedule
Fall, Math, 1st_Period
Fall, History, 2nd_Period
Fall, Science, 3rd_Period
Student
Chris
Kim
StudentEnroll
Math, Chris
Science, Kim
Science, Chris
History, Kim
现在,我要展示的是这样的:
Student 1st_Period 2nd_Period 3rd_Period
Chris Math Science
Kim History Science
OR ......
Student 1st_Period 2nd_Period 3rd_Period
Chris X X
Kim X X
我希望,我可以看到我如何转动"数据。由于我没有对其进行总结或汇总,因此我不知道这是否是正确的术语。无论如何,我无法弄清楚如何有效地做到这一点。我可以进行大量的数据库查询,但必须有一种更简单的方法。
答案 0 :(得分:4)
您应该能够进行两次数据库查询,(1)您获得所有学生注册(使用适当的其他数据获取),以及(2)您获得所有期间的排序列表。您可能可以远离优化第二个查询(但我个人并不打扰)。
在您的视图中使用defaultdict处理此StudentEnroll列表:
from collections import defaultdict
enrolls = StudentEnroll.objects.filter(semester=semester).values_list(
'student__name', 'schedule__course', 'schedule__semester_period__name')
# Fetch all the enrolled data; this puts them in a list of tuples like
# [("Chris", "Math", "1st_Period"), ("Kim", "Science", "3rd_Period"), ... ]
periods = SemesterPeriod.objects.values_list('name', flat=True).order_by('name')
# get names of all periods in a flat list like: ['1st_Period', '2nd_Period', '3rd_Period']
period_dict = dict([(period,i) for i,period in enumerate(periods)])
# enumerate(periods) is a generator that has data in the form
# [(0, '1st_Period'), (1, '2nd_Period'), (2, '3rd_Period')] -- it enumerates the list.
# I then use a list comprehension to reverse it:
# [(period,i) for i,period in enumerate(periods)] is
# [('1st_Period', 0), ('2nd_Period', 1), ...]
# and then convert that list of paired tuples into a dictionary:
# {'1st_Period': 0, '2nd_Period': 1, '3rd_Period': 2}
# period_dict['3rd_Period'] returns 2; indicating that classes that are third period
# should fall into a students schedule in the third slot of the list
# (first element of list is 0)
students_dict = defaultdict(lambda: [""]*len(periods))
# a defaultdict that when a new student (not previously stored) is seen
# initializes that student to have an empty schedule.
# the empty schedule is an empty list that is as long as the number of periods,
# with each period an empty string ''
# student_dict once fully populated will be of form
# {'Chris': ['Math', '', 'Science'], 'Kim': ['', 'History', 'Science']}
# Note student_dict['Chris'] = ['Math', '', 'Science'] and
# student_dict['Chris'][0] = 'Math'.
for (student_name, course, period) in enrolls:
students_dict[student_name][period_dict[period]] = course
# go through the list of enrolls and assign courses to the schedule in the appropriate spots.
student_list = list(student_dict.items())
# [['Chris', ['Math', '', 'Science']], ['Kim', ['', 'History', 'Science']],]
然后通过上下文变量将student_list和句点返回到模板,并使用类似
的内容<table>
<thead>
<tr>
<th>Student</th>
{% for per in periods %}
<th>{{ per }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for student_row in student_list %}
<tr><th>{{ student_row.0 }}</th>
{% for class in student_row.1 %}
<td>{{ class }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>