Django can I have any more good orm?

Question:

This related to this previous question: Django models and orm and foreign key problems

Here are some changes in the MemosInProduct model:

class MemosInProduct(models.Model):
    product_key=models.ForeignKey(ProductInOrder, on_delete=models.CASCADE, related_name="product_key")

    memo=models.CharField(max_length=100)

    _is_deleted=models.BooleanField(default=False)
    blahblah some codes...

I added _is_deleted field is need for soft delete functions.

Except MemosInProduct, any model definitions and querying targets are same as previous questions.

That means I still need all of OrderList data with related all of data combine with it (product, memos):

EXCEPTED

order_list[0].order_key[0].product_key[0].memo
order_list[0].order_key[0].product_key[1].memo
order_list[0].order_key[1].product_key[0].memo
...

Here is the start this question: I realized that need filtering a specific table. That means, I only need do filtering MemosInProduct table.

With accepted answer by Almabud’s, I tried many orm queries and finally get:

OrderList.object.prefetch_related(
            Prefetch('order_key', queryset=ProductInOrder.object.prefetch_related(
                Prefetch('product_key', queryset=MemosInProduct.object.all().filter(_is_deleted=False))).all()
            )
        ).all()

It works for my goal. All of OrderList and ProductInOrder are displayed well, but only MemosInProduct table has been filtered.

But I want to know that this query has optimized or not. At least, I want to know that this query has no N+1 problems.

Additionally, I would appreciate it if you could let me know if there are any other improvements to the query.

Thank you for read this looong question.

Asked By: Loire

||

Answers:

The alternative way can be the use of an independent Prefetch, so the two alternatives are:

Nested prefetch:
OrderList.object.prefetch_related(
    Prefetch(
        'order_key',
        queryset=ProductInOrder.object.prefetch_related(
            Prefetch(
                'product_key',
                queryset=MemosInProduct.object.filter(_is_deleted=False)
            )
        )
    )
)
Independent prefetch:
OrderList.object.prefetch_related(
    'order_key',
    Prefetch(
        'order_key__product_key',
        queryset=MemosInProduct.object.filter(_is_deleted=False)
    )
)

Both approaches will produce the same result while avoiding the N+1 problem. However, using an independent prefetch may provide a slightly better performance than using a nested prefetch. The reason for this is that in the nested prefetch approach, distinct querysets are created for each ProductInOrder row. The ORM should "merge" these querysets to avoid the N+1 problem, this process requires additional computational resources (depending on the size and complexity of the querysets to be merged).

Answered By: Jonathan Quispe
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.