有时在 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)
这可以在模板中完成吗?
注意:我知道我可以通过在过滤器上返回“汽车”的上下文和“零件”的上下文来很容易地在视图中执行此操作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
. 此外,首先制作这个视图只是更多的工作。