2009-02-11 71 views
3

我正在努力設計一個Django應用程序。鑑於以下型號:在桌面設計問題中顯示多個相關的Django模型

class A(models.Model): 
    name = models.CharField(max_length=255) 

class B(models.Model): 
    name = models.CharField(max_length=255) 
    a = models.ForeignKey(A) 

class C(models.Model): 
    val = models.IntegerField() 
    b = models.ForeignKey(B) 

我想的視圖/模板顯示一個HTML表,其中顯示在第一列中所有的A的對象,在第二列中所引用到的所有B對象(由A分組) A和最後一列中每個B都引用的C對象的所有val的總和。對於每個A對象都有一個總和。 下面的例子顯示了我在尋找:

 
A1.name | B1.name [where FK to A1] | sum(C.val) [where FK to B1] 
A1.name | B2.name [where FK to A1] | sum(C.val) [where FK to B2] 
A1.name |     Total | sum(C.val) [where FK to Bx (all B that have FK to A1] 
A2.name | B3.name [where FK to A2] | sum(C.val) [where FK to B3] 
A2.name |     Total | sum(C.val) [where FK to Bx (all B that have FK to A2] 

誰能給我一個建議如何設計這樣的問題(不幸的是,我的代碼往往在相當混亂結束了)?

我應該用合適的方法擴展模型類嗎?爲視圖中的整個表數據執行自定義查詢?只需通過經理獲取所有對象並完成模板中的大部分工作?

感謝您的每一個答案。

Regards,

Luke。

回答

5

如果您有該日期模型,以便您可以獲取所有b s,然後將它們分組a並計算總金額。代碼可能是這樣的:

查看:

from django.utils.itercompat import groupby 

def view(request): 
    bs = B.objects.all().annotate(sum_of_c_val=Sum('c.val'))\ 
         .select_related('a') 
    b_by_a = [ 
      { 
       'grouper': key, 
       'list': list(val), 
       'total': sum([b.sum_of_c_val for b in val]) 
      } 
      for key, val in 
      groupby(bs, lambda b: b.a) 
    ] 

    return render_to_response('tmpl.html', {'b_by_a': b_by_a}) 

而且模板:

{% for b_group in b_by_a %} 
    {% for b in b_group.list %} 
    <tr> 
     <td>{{b_group.grouper.name}}</td> 
     <td>{{b.name}}</td> 
     <td>{{b.sum_of_c_val}}</td> 
    </tr> 
    {% endfor %} 
    <tr> 
     <td>{{b_group.grouper.name}}</td> 
     <td>Total</td> 
     <td>{{b_group.total}}</td> 
    </tr> 
{% endfor %} 

編輯:

使用Django 1.0兼容必須更換annotate通話與extra選擇或蟒蛇中的金額計算。

  1. 隨着子查詢:

    bs = B.objects.all().extra(
        select={ 
         'sum_of_c_val': 'SELECT SUM(app_c.val) FROM app_c WHERE app_c.b_id=app_b.id' 
        }).select_related('a') 
    #... 
    

    app - 應用程序名稱

  2. 這-蟒計算:

    bs = B.objects.all().select_related('a') 
    for b in bs: 
        b.sum_of_c_val = sum(map(int, b.c.all().values_list("val", flat=True))) 
    #... 
    

    但是它產生N個附加查詢(其中N = len(bs)

+0

謝謝,這看起來比我想出來的要乾淨得多,但是這隻適用於Django v1.1及更高版本,對嗎? – Lukas 2009-02-11 13:22:25

1

免責聲明:我是一個Django初學者自己,但如果我理解它的基本概念,正確的,那麼:

既然你想要的看法是 - 就像你說的 - 只是一個底層數據的視圖,那麼你應該在視圖模塊中進行排序和分組。我認爲你不應該混淆模型(這只是數據),也不應該使用模板(這只是視圖的佈局)。