django select_related in template

时间:2013-10-22 16:44:52

标签: python html sql django templates

有时在django模板中使用select_related是有意义的。例如,假设我有一个扩展DetailView的类

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'的上下文和带有select_related('manufacturer')的'parts'的上下文来非常轻松地在视图中执行此操作,但是与之相比,它的代码要多得多。我上面使用过的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。此外,首先制作此视图还需要做更多的工作。

1 个答案:

答案 0 :(得分:19)

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 %}