django select_related w szablonie

Czasami ma sens użycie select_related w szablonie django. Na przykład powiedzmy, że mam klasę rozszerzającą DetailView

class DemoCarView(DetailView):
    model = Car

Oparty na następującym wymyślonym modelu

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

Szablon HTML jest wtedy

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

To działa idealnie, aby uzyskać samochód, części, które go tworzą i producentów tych części. Jednak w tym celu użyjemy zapytań SQL 2 + number_of_parts. Łatwo to naprawić:

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

Teraz uruchamiane jest optymalne 2 zapytania. Jednak,select_related dołącza do części z każdym posiadanym kluczem obcym. Czy istnieje sposób na ograniczenie tego tylko do pożądanych powiązanych tabel. W Pythonie to po prostu:

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

Czy można to zrobić w szablonie?

Uwaga: Wiem, że bardzo łatwo mogę to zrobić w widoku, zwracając kontekst „samochodu” i kontekstu „części” za pomocąselect_related('manufacturer') na filtrze, ale jest to trochę więcej kodu w porównaniu do podklasy DetailView, której użyłem powyżej. Coś takiego:

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

Wymaga to jednak, aby szablon był bardziej szczegółowy w tym widoku, ponieważ teraz będzie musiał użyć kontekstu „części”, a niecar.part_set.all. Poza tym, to po prostu więcej pracy, aby ten widok był na pierwszym miejscu.

questionAnswers(1)

yourAnswerToTheQuestion