【问题标题】:django select_related in template模板中的 django select_related
【发布时间】:2013-10-31 16:01:08
【问题描述】:

有时在 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。此外,首先制作此视图需要更多的工作。

【问题讨论】:

    标签: python html sql django templates


    【解决方案1】:

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

    【讨论】:

    • 这是一个很好的解决方案,我实际上没有意识到您可以访问模板中的方法和模型中的part_set。谢谢。
    猜你喜欢
    • 2016-05-13
    • 2017-05-25
    • 2011-10-01
    • 2019-05-04
    • 2016-07-02
    • 2011-12-16
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    相关资源
    最近更新 更多