[Fixed]-Prefetch alternative vs Filter directly in template

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

Leave a comment