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