从 Django 中的所有相关对象获取信息

我正在尝试做一些非常简单的事情,但我是 Django 的新手。我为正在进行的实验设置了一个测验系统。models.py 中的相关条目如下:

class Flavor(models.Model):
  name = models.CharField(max_length=100)

  def __unicode__(self):
    return self.name

class Passage(models.Model):
  name = models.CharField(max_length=100)

  def __unicode__(self):
    return self.name

class PassageText(models.Model):
  passage = models.ForeignKey(Passage)
  flavor = models.ForeignKey(Flavor)
  contents = models.TextField()

  def __unicode__(self):
    return "[%s#%s]" % (self.passage, self.flavor)

class Question(models.Model):
  passage = models.ForeignKey(Passage)
  text = models.TextField()

  def __unicode__(self):
    return "[%s#%s]" % (self.passage, self.text)

class AnswerOption(models.Model):
  question = models.ForeignKey(Question)
  text = models.TextField()
  is_correct = models.BooleanField(default=False)

  def __unicode__(self):
    return "[%s#%s]" % (self.question, self.text)

class TestSubject(models.Model):
  GENDER_CHOICES = ( ('M','Male'), ('F','Female'), )
  EDUCATION_CHOICES = ( ('SH', 'Some high school'), ('HS', 'High school diploma'), ('SC', 'Some college'), ('CD', 'College degree'), ('MD', 'Master\'s degree'), ('PH','PhD or higher education'), )
  GPA_CHOICES = ( ('1', '1.0-1.5'), ('2', '1.5-2.0'), ('3', '2.0-2.5'), ('4', '2.5-3.0'), ('5', '3.0-3.5'), ('6', '3.5-4.0'), ('7', '4.0-4.5'), ('8', '4.5-5.0'), )

  ip = models.CharField(max_length=30)
  completed = models.BooleanField(default=False)
  created_time = models.DateTimeField(default=datetime.now)
  time_used = models.IntegerField(default=0, help_text='number of seconds used for test')

  age = models.PositiveIntegerField()
  gender = models.CharField(max_length=2, choices=GENDER_CHOICES)
  education = models.CharField(max_length=2, choices=EDUCATION_CHOICES)
  school = models.CharField(max_length=200)
  grad_year = models.PositiveIntegerField()
  gpa = models.CharField(max_length=2, choices=GPA_CHOICES)
  sat_verbal = models.PositiveIntegerField(blank=True)
  sat_math = models.PositiveIntegerField(blank=True)
  sat_writing = models.PositiveIntegerField(blank=True)
  sat_overall = models.PositiveIntegerField(blank=True)
  english_is_your_first_language = models.BooleanField()
  kerberos_name_if_applying_for_900_credit = models.CharField(max_length=200, blank=True)

  def __unicode__(self):
    return "[%s#%s]" % (self.ip, self.created_time)

class TestSequence(models.Model):
  subject = models.ForeignKey(TestSubject)
  order = models.IntegerField(help_text='1..n')
  pt = models.ForeignKey(PassageText)
  time_used = models.IntegerField(default=0, help_text='number of seconds used for test')

  def __unicode__(self):
    return "[%s#%d]" % (self.subject, self.order)

class QuestionSequence(models.Model):
  tseq = models.ForeignKey(TestSequence)
  order = models.IntegerField(help_text='0..n')
  question = models.ForeignKey(Question)
  selectedanswer = models.ForeignKey(AnswerOption, blank=True, null=True, default=None)

  def __unicode__(self):
    return "[%s#%d]" % (self.tseq, self.order)

我希望有一个页面,它只是给我一个所有 TestSubject 对象(及其所有属性)的表格,以及他们做了哪些段落以及他们在该段落中答对了多少个问题的列表。

2、解决方案

为了解决这个问题,我们可以使用 Django 的 ORM(对象关系映射器)来访问和查询数据库中的对象。我们可以使用以下查询来获取所有 TestSubject 对象以及他们做了哪些段落和答对了多少个问题:

from django.db.models import Count

# 获取所有 TestSubject 对象
test_subjects = TestSubject.objects.all()

# 为每个 TestSubject 对象获取他们做了哪些段落和答对了多少个问题
for test_subject in test_subjects:
    # 获取 TestSubject 对象做过的所有段落
    passages = TestSequence.objects.filter(subject=test_subject).values('pt__passage__name').annotate(count=Count('question'))

    # 获取 TestSubject 对象在每个段落中答对了多少个问题
    correct_answers = QuestionSequence.objects.filter(tseq__subject=test_subject, selectedanswer__is_correct=True).values('tseq__pt__passage__name').annotate(count=Count('question'))

    # 输出 TestSubject 对象的信息以及他们做了哪些段落和答对了多少个问题
    print("TestSubject: ", test_subject)
    print("Passages:")
    for passage in passages:
        print(" - ", passage['pt__passage__name'], " - ", passage['count'])
    print("Correct Answers:")
    for correct_answer in correct_answers:
        print(" - ", correct_answer['tseq__pt__passage__name'], " - ", correct_answer['count'])

这段代码会为每个 TestSubject 对象输出以下信息:

  • TestSubject 对象的属性值
  • TestSubject 对象做过的所有段落以及他们答对了多少个问题
  • TestSubject 对象在每个段落中答对了多少个问题

你可以将这段代码复制到你的 Django 项目中的 views.py 文件中,并创建一个相应的模板文件来显示查询结果。