Reputation: 33
I want to optimize the looping code using django orm as it is taking 41 queries because of the loop was shown in django-debug-toolbar, I have stated my models with the django ORM and there is a loop where i need to optimize using ORM approach so that i can avoid a loop.
class Bills(models.Model):
library=models.ForeignKey(Library,null=True)
customer=models.ForeignKey(Customer, null=True)
total_price = models.FloatField()
History = '1'
Physics = '2'
Maths = '3'
Book_Category=(
(History,'History'),
(Physics,'Physics'),
(Maths,'Maths')
)
book_category_type=models.CharField(max_length=2,choices=Book_Category)
This is the Bill model storing the all the bills of specific customer.
class LibraryOrder(models.Model):
hotel=models.ForeignKey(Hotel,null=True)
library = models.ForeignKey(Library,null=True)
customer=models.ForeignKey(Customer,null=True)
library_item = models.ForeignKey(LibraryItem,null=True)
quantity = models.FloatField()
total_price = models.FloatField()
comments=models.TextField(null=True)
bill=models.ForeignKey(Bills,null=True)
ORDER_STATUS = (
(NOT_PROCESSED, 'NotProcessed'),
(PROCESSING, 'Processing'),
(PROCESSED,'processed'),
)
order_status = models.CharField(max_length=3, choices=ORDER_STATUS, default=NOT_PROCESSED)
This is the Order model when some customer orders for some book in the library item.
Right now i am using this :
customers = Customer.objects.filter(library="1").exclude(customer_status='2')
bills = Bills.objects.filter(library="1", customer=customers, book_category_type="1")
for bill in bills:
# if bill.order_type == "1":
not_processed_order = LibraryOrder.objects.filter(bill=bill, order_status="1")
notprocessed_lists.append(not_processed_order)
processing_order = LibraryOrder.objects.filter(bill=bill, order_status="2")
processing_lists.append(processing_order)
processed_order = LibraryOrder.objects.filter(bill=bill, order_status="3")
processed_lists.append(processed_order)
The bills which is getting looped is the loop where i am getting the array of bills by that orm, as in library order i have bill as foreign key i am using to get the order details and pushing to the array for displaying in the html.
I want to optimize the django orm approach which i have specified to two lines into single line, Those lists are separate as it is displaying in the separate tabs in html
Upvotes: 1
Views: 512
Reputation: 1200
not_processed_order = LibraryOrder.objects.filter(bill__library="1", bill__book_category_type="1", order_status="1", bill__customer__library='1').exclude(bill__customer__status='2')
processing_order = LibraryOrder.objects.filter(bill__library="1", bill__book_category_type="1", order_status="2", bill__customer__library='1').exclude(bill__customer__status='2')
processed_order = LibraryOrder.objects.filter(bill__library="1", bill__book_category_type="1", order_status="3", bill__customer__library='1').exclude(bill__customer__status='2')
Upvotes: 4
Reputation: 16050
In this specific scenario you can use prefetch_related
with custom Prefetch
object/s to prefetch the necessary data and not make any queries inside the loop.
customers = Customer.objects.filter(library="1").exclude(customer_status='2')
bills = Bills.objects.filter(library="1", customer=customers, book_category_type="1").prefetch_related(
Prefetch('libraryorder_set', queryset=LibraryOrder.objects.filter(order_status="1"), to_attr='not_processed_orders'),
Prefetch('libraryorder_set', queryset=LibraryOrder.objects.filter(order_status="2"), to_attr='processing_orders'),
Prefetch('libraryorder_set', queryset=LibraryOrder.objects.filter(order_status="3"), to_attr='processed_orders'),
)
for bill in bills:
notprocessed_lists.append(bill.not_processed_orders)
processing_lists.append(bill.processing_orders)
processed_lists.append(bill.processed_orders)
This way you will have 3 queries (1 query per prefetch
object) instead of 40+.
You can optimize if further to 1 query, but you will have to do some more work in the python code:
customers = Customer.objects.filter(library="1").exclude(customer_status='2')
bills = Bills.objects.filter(library="1", customer=customers, book_category_type="1").prefetch_related('libraryorder_set')
for bill in bills:
not_processed_orders = []
processing_orders = []
processed_orders = []
for order in bill.libraryorder_set.all():
if order.status == '1':
not_processed_orders.append(order)
elif order_status == '2':
processing_orders.append(order)
elif order_status == '3':
processed_orders.append(order_status)
notprocessed_lists.append(bill.not_processed_orders)
processing_lists.append(bill.processing_orders)
processed_lists.append(bill.processed_orders)
However in order to lean how to fish, my advice it to take a look at the following articles from the docs:
Upvotes: 0