2013-10-22 157 views
7

有時在django模板中使用select_related是有意義的。例如,說我有基於以下做作模型擴展的DetailViewdjango select_related模板

class DemoCarView(DetailView): 
    model = Car 

# Cars 
class Car(models.Model): 
    name = models.CharField(max_length=32) 

# Manufacturers 
class Manufacturer(models.Model): 
    name = models.CharField(max_length=32) 

# Parts 
class Part(models.Model): 
    name = models.CharField(max_length=32) 
    car = models.ForeignKey(Car) 
    manufacturer = models.ForeignKey(Manufacturer) 

HTML模板然後

{{ car.name }} 
<ul> 
{% for part in car.part_set.all %} 
    <li>{{ part.name }} - {{ part.manufacturer.name }} </li> 
{% endfor %} 
</ul> 

這工作完全讓汽車,構成它的部件以及這些部件的製造商。但是,這將使用2 + number_of_parts SQL查詢來執行此操作。輕鬆修復如下:

{{ car.name }} 
<ul> 
{% for part in car.part_set.select_related.all %} 
    <li>{{ part.name }} - {{ part.manufacturer.name }} </li> 
{% endfor %} 
</ul> 

現在運行2個查詢的最佳值。但是,select_related正在將零件與每個外鍵相連接。有沒有辦法限制這只是所需的相關表。在Python中,它只是:

Part.objects.select_related('manufacturer').filter(car=car) 

這可以在模板中完成嗎?

注意:我知道我可以非常容易地在視圖中通過在過濾器上返回'car'和一個用於'parts'的select_related('manufacturer')的上下文來實現此操作,但與DetailView子控件相比,上面使用的類。事情是這樣的:

class DemoCarViewPreload(TemplateView): 
    template_name = 'demo/car_detail_preload.html' 
    def get_context_data(self, **kwargs): 
     context = super(DemoCarViewPreload, self).get_context_data(**kwargs) 
     car = Car.objects.get(pk=kwargs.get('pk')) 
     context['car'] = car 
     context['parts'] = Part.objects.select_related('manufacturer').filter(car=car) 
     return context 

然而,這需要模板更具體的這一觀點,因爲它現在需要使用「零件」上下文,而不是car.part_set.all。而且,首先製作這個視圖只是更多的工作。

回答

18

如何在Car模型上使用簡單的方法?

class Car(models.Model): 
    ... 
    def parts_with_manufacturers(self): 
     return self.part_set.select_related('manufacturer') 

然後

{% for part in car.parts_with_manufacturers %} 
    <li>{{ part.name }} - {{ part.manufacturer.name }} </li> 
{% endfor %} 
+0

這是一個很好的解決方案,我並沒有真正實現,你可以訪問模型模板和part_set方法。謝謝。 – dpwrussell