在django中优化查询

时间:2016-08-17 10:41:52

标签: python mysql django django-models orm

我想使用django orm来优化循环代码,因为它有41个查询,因为循环显示在django-debug-toolbar中,我已经用django ORM声明了我的模型,并且我需要一个循环使用ORM方法优化,以便我可以避免循环。

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)

这是存储特定客户的所有账单的账单模型。

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)

这是订单模型,当某些客户订购了库项目中的某些图书时。

现在我正在使用它:

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)

正在循环的账单是我通过该orm获取账单数组的循环,因为在库顺序中我有账单作为外键我用来获取订单详细信息并推送到阵列进行显示html。

我想优化django orm方法,我指定将两行分为单行,这些列表是分开的,因为它显示在html的单独选项卡中

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:0)

在此特定方案中,您可以使用prefetch_related和自定义Prefetch对象来预取必要的数据,而不在循环内进行任何查询。

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)

这样您将有3个查询(每个prefetch对象1个查询)而不是40个。

你可以进一步优化1个查询,但是你需要在python代码中做更多的工作:

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)

然而,为了倾斜如何钓鱼,我的建议是看看文档中的以下文章: