2011-03-07 37 views
2

我正在處理零件數據庫,其中每個零件號也可以是一個裝配體,這意味着它由任意數量的其他零件組成(並且循環可以繼續,子部分由更多部分組成等)。因此,有兩個數據庫表,一個用於零件信息,另一個用於關係信息 - 與其「子部分」編號鏈接的零件編號。請記住,「程序集」,「部件」和「子部件」最終都只是「部件(有點令人困惑,但它允許更乾和多功能的數據庫)需要幫助使用來自Select_related()查詢集的數據

我目前使用的是select_related調用以跟隨在我的模型中使用的ForeignKeys。但是,因爲我的查詢可能返回的不止是單個結果(如果有多個子部分),我不能使用「get」查找,而是使用「filter」。 - 我不能按照文檔中顯示的所有基於get查詢的示例。

select_related查詢似乎正在抓取我想要的內容(基於DjangoDebugToolbar顯示的原始SQL查詢)。但是,我不知道如何調用它!從相關表中顯示值的正確語法或方法是什麼?我怎麼能循環返回的查詢集中的每個實例?從模板下面的代碼段應該最有效地顯示我想要獲得的結果。謝謝。

#---------------- 
#MODEL SNIPPET 
#---------------- 
class Part(models.Model): 
    ISC_CHOICES = (#intentionaly removed for this question 
    ) 
    part_no = models.CharField(max_length=15, primary_key=True) 
    description = models.CharField(max_length=40, blank=True, null=True) 
    isc = models.CharField(max_length=2, choices=ISC_CHOICES) 
    rev = models.CharField(max_length=2, blank=True, null=True) 

#this table relates subparts to the part model above- basically is a manual many-to-many field 
class PartAssembly(models.Model): 
    id = models.AutoField(primary_key=True) 
    part_no = models.ForeignKey(Part, related_name="partno_set") 
    subpart = models.ForeignKey(Part, related_name="subpart_set") 
    qty = models.IntegerField(max_length=3) 
    item_no = models.IntegerField(max_length=3) 


#---------------- 
#VIEW SNIPPET 
#---------------- 
def assembly_details(request, assembly_no): #assembly_no passed through URL 
    context_instance=RequestContext(request) 
    subpart_list = PartAssembly.objects.filter(part_no=assembly_no).select_related() 
    return render_to_response('assembly_details.html', locals(), context_instance,) 


#------------------- 
# TEMPLATE SNIPPET 
#------------------- 
{% for partassembly in subpart_list %} 
# obviously, this loop doesnt return anything for my part.foo variables below 
# it does work for the partassembly.bar 
     <tr> 
      <td>{{ partassembly.item_no }}</td> #EDIT: comments are correct 
      <td>{{ partassembly.subpart }}</td> #partassembly.subpart.part_no 
      <td>{{ part.description }}</td> #partassembly.subpart.description 
      <td>{{ part.rev }}</td>  #partassembly.subpart.rev 
      <td>{{ partassembly.qty }}</td> 
      <td>{{ part.isc }}</td>   #partassembly.subpart.isc 
     </tr> 

感謝所有幫助

回答

4

我不知道您的問題是究竟。請記住,select_related()不會以任何方式更改相關實例的對象訪問權 - 它所做的只是預先緩存它們。所以你參考partassembly.part_no.rev等等,就好像你沒有使用select_related一樣。

+0

我試圖在最小化查詢的同時將數據調用到我的模板中,select_related似乎是解決方案。我在這裏的主要問題實際上只是不知道將相關數據表調入模板的語法。我的大部分django經驗都是簡單的數據庫交互,所以我在使用更高級的django數據庫查詢方面有點新手。 – 2011-03-07 23:38:08

+0

這正是我需要做的。所以基本上你只需要調用queriedmodelname.foriegnkeyname.propertyofthatkey。爲什麼我無法從我不確定的文檔中獲取這些信息。我一直在嘗試雙下劃線__相關的字段查找。謝謝! – 2011-03-08 14:04:34

2

所有select_related確實,正在熱切地獲取您模型中聲明爲ForeignKey的字段。它試圖避免額外的數據庫調用,它不會讓你奇蹟般地訪問額外的字段。

在您的示例中,這意味着訪問partassembly.subpart不會導致額外的數據庫選擇,因爲它是通過PartAssembly.objects.filter()呼叫急切地提取的。

您的數據模型似乎不正確,但我們會在一分鐘內得出結論。首先,我將向您展示如何訪問當前數據模型中的所有零碎部分。

{% for partassembly in subpart_list %} 
     <tr> 
      <td>{{ partassembly.item_no }}</td> 
      {% for subpart in partassembly.subpart.subpart_set %} # database hit 
       <td>{{ subpart.subpart }}</td> 
       <td>{{ subpart.subpart.description }}</td> # database hit 
       <td>{{ subpart.subpart.rev }}</td>   
       <td>{{ subpart.qty }}</td> 
       <td>{{ subpart.subpart.isc }}</td> 
      {% endfor %} 
     </tr> 

不幸的是,你無法知道你需要多少程度的遞歸。您可以訪問原始PartAssembly中的零件,並且可以從該零件到達PartAssembly的集合,但是沒有簡單的方法可以達到第一個PartAssembly內所有零件的PartAssembly集合。哇,那真是一口!

現在,到您的數據模型。

假設您有一個稱爲「3毫米螺釘」的零件。這聽起來像它可以用於一些不同的大會(我故意不使用'ies'複數形式)。所以你有一個名爲書桌的大會和一個名爲主席的大會。每個使用許多這些3mm螺絲。你想描述如何建立一個桌面。

desk = PartAssembly.objects.filter(id=assemblyid) 
part = desk.subpart # lets pretend this returns a 3mm screw 
subassemblies = part.subpart_set.all() 
for a in subassemblies: 
    a.subpart.description # could be a Chair, or a Desk, or anything really! 

發生這種情況是因爲3mm螺絲釘(或任何零件)的單個實例在所有組件之間共享。你根本沒有真正複製ManyToMany表。你的數據模型是說許多裝配中都可以使用單個零件。

我認爲你真的想說的是,一個大會可以成爲另一個大會的一部分。每個大會作爲與其建設相關的多個部分。

class Assembly(models.Model): 
    parent = models.ForeignKey('self', null=True, blank=True, related_name='children') 
    parts = models.ManyToManyField(Part) 
    name = models.CharField(max_length=..) 

現在,當你想建立一個椅子上,你可以這樣做:

assembly = Assembly.objects.get(name='Chair') 
children = assembly.children.all() 
print assembly 
for part in assembly.parts: 
    print part 
# now you iterate over the tree of children, printing their parts as you go 

所以,你的裝配模型現在已經轉變成其他大會的一個樹形結構,每個都包含自己的一套零件。現在您可以認識到這是一個Tree結構,您可以研究如何在Django中的數據庫中表示此結構。

幸運的是,有一個圖書館正是這樣做的。 django-mptt存在以幫助您表示樹結構。它爲您提供遍歷整個樹的方法,並描述模板中的每個樹。

我知道我可能幫助你讓更多的工作比你想象的要多,但我認爲這對你真的會有幫助。

祝你好運。

+0

這是相當的答案!不幸的是,我傾向於在一天結束的時候在這裏發帖,當時我無法自己弄清楚,但是我的所有文件仍然在工作,我無法在家中試用它們!哈哈。感謝您的幫助,我會檢查出來,並可能在早上接受它。 – 2011-03-07 23:33:25

+0

我故意避開區分頂級組件與子組件等零件等。使用此應用程序的方式要求在任何給定時間可調用特定的子組件,並且部件不會始終處於同一層組件。我會檢查出mptt庫。可能當我的模型無法正常工作時,我會回到這篇文章。這是(目前)一個研發類型的項目,所以我不會害怕掉到我的臉上,也不必嘗試新的東西(閱讀:沒有截止日期!)謝謝喬希 – 2011-03-08 14:44:10