模板中的django select_related [英] django select_related in template

查看:540
本文介绍了模板中的django select_related的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 类DemoCarView(DetailView):
model = Car

基于以下设计模型

 #汽车
类汽车(models.Model):
name = models.CharField(max_length = 32)

#制造商
类制造商(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 car.part_set.all%中的部分}
< li> {{part.name}} - {{part.manufacturer.name}}< / li>
{%endfor%}
< / ul>

这对于获得汽车,组成它的零件以及这些零件的制造商来说非常合适。但是,这将使用2 + number_of_parts SQL查询来执行此操作。轻松修复如下:

  {{car.name}} 
< ul>
{%for car.part_set.select_related.all%中的部分}
< li> {{part.name}} - {{part.manufacturer.name}}< / li>
{%endfor%}
< / ul>

现在运行最佳的2个查询。但是, select_related 正在将部件与每个外键相连接。有没有办法限制这只是所需的相关表。在Python中,它只是:

$ p $ Part.objects.select_related('manufacturer')。filter(car = car)

这可以在模板中完成吗?



我知道我可以很容易地在视图中做到这一点,通过在过滤器上返回'car'和一个用于'code> select_related('manufacturer')的零件'的上下文,但是与上面使用的DetailView子类相比,它的代码更多一些。就像这样:

$ p $ 类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 $然而,这需要模板更加具体到这个视图,因为它现在需要使用'b




$ b

零件'上下文而不是 car.part_set.all

解决方案

如何在<$ c上使用简单的方法$ c $>车模型?

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

,然后是

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


Sometimes it makes sense to use select_related in a django template. For example, say I have a class extending DetailView

class DemoCarView(DetailView):
    model = Car

Based on the following contrived model

# 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)

The html template is then

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

This works perfectly to get the car, the parts that comprise it, and the manufacturers of those parts. However, this will use 2+number_of_parts SQL queries to do so. Easily fixed like so:

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

Now the optimum of 2 queries is run. However, select_related is joining the Parts with every Foreign Key that it has. Is there a way to restrict this to just the desired related tables. In Python it's just:

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

Can this be done in the template?

Note: I know I can do this in the view very easily by returning a context for 'car' and one for 'parts' with select_related('manufacturer') on the filter, but it's quite a bit more code compared to the DetailView sub-class I've used above. Something like this:

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

However, this requires the template to be more specific to this view as it will now need to use the 'parts' context rather than car.part_set.all. Also, it's simply more work to make this view in the first place.

解决方案

How about a simple method on the Car model?

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

and then

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

这篇关于模板中的django select_related的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆