Все select_related
делает, охотно выбирает поля, объявленные как ForeignKey
в вашей модели. Он пытается избежать дополнительных вызовов базы данных, он волшебным образом не дает вам доступ к дополнительным полям.
В вашем примере это означает, что доступ к partassembly.subpart
не приведет к дополнительному выбору базы данных, поскольку он был с нетерпением извлечен с помощью вызова PartAssembly.objects.filter()
.
Ваша модель данных неверна, но мы вернемся к этому через минуту. Сначала я покажу вам, как получить доступ ко всем элементам с помощью вашей текущей модели данных.
{% for partassembly in subpart_list %}
<tr>
<td>{{ partassembly.item_no }}</td>
{% for subpart in partassembly.subpart.subpart_set %} # database hit
<td>{{ subpart.subpart }}</td>
<td>{{ subpart.subpart.description }}</td> # database hit
<td>{{ subpart.subpart.rev }}</td>
<td>{{ subpart.qty }}</td>
<td>{{ subpart.subpart.isc }}</td>
{% endfor %}
</tr>
К сожалению, у вас нет возможности узнать, как далеко вы должны пройти. Вы можете получить доступ к детали в исходной части PartAssembly и получить доступ к набору PartAssemblys из этой детали, но нет простого способа получить набор PartAssembly для всех деталей в пределах первой PartAssembly. Вау, это был полный рот!
Теперь перейдем к вашей модели данных.
Скажем, у вас есть деталь, которая называется "3-миллиметровый винт". Звучит так, как будто его можно использовать для ряда различных сборок (я намеренно не использую форму множественного числа 's'). Итак, у вас есть Ассамблея, которая называется Desk, и Ассамблея, которая называется Председатель. Каждый использует много из этих 3 мм винтов. Вы хотите описать, как построить стол.
desk = PartAssembly.objects.filter(id=assemblyid)
part = desk.subpart # lets pretend this returns a 3mm screw
subassemblies = part.subpart_set.all()
for a in subassemblies:
a.subpart.description # could be a Chair, or a Desk, or anything really!
Это происходит потому, что один экземпляр 3-миллиметрового винта (или ЛЮБОЙ детали) используется всеми сборками. Вы действительно не реплицируете таблицу ManyToMany вообще. Ваша модель данных говорит, что одна деталь может использоваться во многих сборках.
Я думаю, вы действительно хотите сказать, что Ассамблея может быть частью другой Ассамблеи. Каждая сборка как ряд деталей связана с ее конструкцией.
class Assembly(models.Model):
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
parts = models.ManyToManyField(Part)
name = models.CharField(max_length=..)
Теперь, когда вы хотите построить стул, вы можете сделать что-то вроде:
assembly = Assembly.objects.get(name='Chair')
children = assembly.children.all()
print assembly
for part in assembly.parts:
print part
# now you iterate over the tree of children, printing their parts as you go
Итак, ваша модель сборки теперь преобразована в древовидную структуру других сборок, каждая из которых содержит свой собственный набор деталей. Теперь, когда вы можете распознать, что это древовидная структура, вы можете исследовать, как представить эту структуру в базе данных в Django.
К счастью, существует библиотека, которая делает именно это. django-mptt существует, чтобы помочь вам представить древовидные структуры. Он дает вам методы для перебора всего дерева и описания каждого дерева в ваших шаблонах.
Я знаю, что, вероятно, помог вам сделать больше работы, чем вы думали, но я думаю, что это действительно поможет вам.
Удачи.