Czasami sensowne jest użycie select_related w szablonie django. Na przykład, że mam klasę rozciągający DetailViewdjango select_related w szablonie
class DemoCarView(DetailView):
model = Car
opiera się na następujących contrived 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 następnie
{{ car.name }}
<ul>
{% for part in car.part_set.all %}
<li>{{ part.name }} - {{ part.manufacturer.name }} </li>
{% endfor %}
</ul>
Działa to doskonale, aby uzyskać samochód, części, które ją tworzą, oraz producentów tych części. Będzie to jednak wymagało użycia 2 + number_of_parts zapytań SQL. Łatwo naprawione w ten sposób:
{{ car.name }}
<ul>
{% for part in car.part_set.select_related.all %}
<li>{{ part.name }} - {{ part.manufacturer.name }} </li>
{% endfor %}
</ul>
Teraz optymalizuje się 2 zapytania. Jednak select_related
dołącza do Części z każdym kluczem obcym, który ma. Czy istnieje sposób, aby ograniczyć to do pożądanych powiązanych tabel. W Pythonie jest to po prostu:
Part.objects.select_related('manufacturer').filter(car=car)
Czy można to zrobić w szablonie?
Uwaga: Wiem, że mogę to zrobić w widoku bardzo łatwo, zwracając kontekst dla "samochodu" i jednego dla "części" z select_related('manufacturer')
na filtrze, ale jest to trochę więcej kodu w porównaniu do podobrazia DetailView klasa, 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 szablon jest bardziej charakterystyczne dla tego widoku, jak to teraz trzeba korzystać z kontekstu „części” zamiast car.part_set.all
. Co więcej, po prostu więcej pracy nad stworzeniem tego widoku.
To dobre rozwiązanie, nie można zrealizować w rzeczywistości metody dostępu w szablonie i part_set w modelu. Dzięki. – dpwrussell