2013-10-24 98 views
3

我在理解如何使用Django遵循多級關係時遇到了一些麻煩。很明顯,我可以使用for循環,但我試圖找到一個更有效的方法來做到這一點(可能訴諸原始SQL)。該模型大致是:Django關注一對多關係

Subject -> Course -> Module -> Question

他們通過外鍵鏈接(例如在Question模塊有一個外鍵指向一個Module)。

下面的作品,但速度很慢,肯定不理想:

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') 

回答

2

如果您的SQL查詢將開始SELECT * FROM Model ...那麼您的Django查詢應該g一般開始Model.objects.filter(...)。所以在這種情況下,您需要類似的東西:

Question.objects.filter(module__course__subject__name = 'Mathematics', 
         num_attempts__gt = 20, 
         avg_score__gt = 0).order_by('avg_score') 
+0

謝謝!我沒有在文檔的正確位置查找。對於未來的讀者,文檔如下: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships 這比'for'循環更快顯而易見的原因:-) –