1
Honestly, I’m not sure if this is going to work, but give it a try:
soproduct = SOproduct.objects.select_related('product__material').prefetch_related(
Prefetch(
'product__material__bomversion_set',
queryset=BOMVersion.objects.default().active().prefetch_related(
Prefetch('bom_set', queryset=BOM.objects.all().prefetch_related('production_order_set'))
),
to_attr='default_active_bomversions'
)
)
And then in the template, you do a simple if-check.
{% for soproduct in list_soproduct %}
{% for bomversion in soproduct.product.material.default_active_bomversions %}
{% for bom in bomversion.bom_set.all %}
{% for production_order in bom.production_order_set.all %}
{% if production_order.soproduct == soproduct %}
do my staff
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
Basically what prefetch_related
do is to fetch related data not via SQL JOINs
(this is what select_related
do), but by doing separate query and then merging the results in python. I think the docs do a pretty good job explaining this.
And by using a custom Prefetch
object we can do two things
1) Alter the default queryset
which django will use doing prefetch_related
(usefull to filter results even more) and
2) Change the attribute into which django will store the prefetched data (by defaults its into the myobject.related_set.all()
this is useful when we do additional filtering which changes the contex of the results and related_set.all()
won’t be appropriate or will be a misleading).