Django如何跟踪一对多关系

3

我有一些困难理解如何使用Django遵循多层级的关系。显然,我可以使用for循环,但我正在尝试找到一种更有效的方法来实现它(可能要求使用原始SQL)。模型大概是这样的:

学科 -> 课程 -> 模块 -> 问题

它们通过外键链接在一起(例如,问题模块具有指向模块的外键)。

以下代码可以工作,但速度相当慢,肯定不是最理想的:

subject = "Mathematics"
courses = Subject.objects.get(name__iexact=subject).course_set.all()
avg_scores = []
for course in courses:
    modules = course.module_set.all()
    for module in modules:
        questions = module.question_set.all().filter(num_attempts__gt=20).filter(avg_score__gt=0).exclude(avg_score__isnull=True).order_by('avg_score')
        for question in questions:
            avg_scores.append(question)

我可以使用以下SQL完成这个任务:

SELECT * FROM question
INNER JOIN module
ON question.module_id=module.id
INNER JOIN course
ON module.course_id=course.id
INNER JOIN subject
ON course.subject_id = subject.id
WHERE subject.name="Mathematics"
AND num_attempts > 20
AND avg_score > 0

有没有一种方法可以做到这样:

avg_scores = Subject.objects.get(name__iexact="Mathematics").course_set.module_set.question_set.filter(num_attempts__gt=20).filter(avg_score__gt=0).exclude(avg_score__isnull=True).order_by('avg_score')
1个回答

2
如果您的SQL查询以 SELECT * FROM Model ... 开始,那么您的Django查询通常应该以 Model.objects.filter(...) 开始。因此,在这种情况下,您需要像这样的内容:
Question.objects.filter(module__course__subject__name = 'Mathematics',
                        num_attempts__gt = 20,
                        avg_score__gt = 0).order_by('avg_score')

谢谢!我猜我没有在文档的正确区域查找。对于未来的读者,文档如下:https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships这比使用for循环明显更快 :-) - Jacob Schaer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接