我目前正在从事一个Django项目,在该项目中我遇到了性能问题,特别是在我的应用程序扩展时.为了提供更好的上下文,我在下面包含了一个真实的代码片段,它代表了我的应用程序的一个性能密集型部分:

from django.db import models

class Order(models.Model):
    # Fields and relationships...

class OrderItem(models.Model):
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    product = models.ForeignKey('Product', on_delete=models.CASCADE)
    quantity = models.PositiveIntegerField()

class Product(models.Model):
    # Fields and relationships...

def calculate_total_price(order_id):
    order_items = OrderItem.objects.filter(order_id=order_id).select_related('product')
    total_price = 0

    for item in order_items:
        product_price = item.product.price
        quantity = item.quantity
        total_price += product_price * quantity

    return total_price

在上面的代码片段中,我有一个与多个OrderItems相关联的订单模型,并且每个OrderItem引用一个Product.calculate_total_price函数用于通过迭代关联的OrderItems来计算给定订单的总价格.但是,随着OrderItems数量的增加,计算速度会显著变慢.

我非常感谢任何关于如何优化此代码片段或任何其他一般Django性能技巧的见解和建议.有没有我应该考虑的特定技术、数据库查询优化、缓存机制或Django特性来增强这段代码的性能?此外,如果您推荐任何性能分析工具或库来识别和解决性能问题,请让我知道.

我热衷于学习优化Django性能的最佳实践和高级技术,因为我希望确保我的应用程序随着其增长而高效地运行.首先感谢您的宝贵帮助!

我不知道如何处理性能问题,所以我不知道从哪里开始优化.

Edit个 包括示例视图代码:

class OrderDetailView(View):
    template_name = 'order_detail.html'

    def get(self, request, order_id):
        order = Order.objects.get(id=order_id)
        total_price = calculate_total_price(order_id)
        context = {
            'order': order,
            'total_price': total_price
        }
        return render(request, self.template_name, context)

推荐答案

您可以通过数据库本身来计算这一点,即使在与获取订单的查询相同的查询中也是如此:

from django.db.models import F, Sum, Value
from django.db.models.functions import Coalesce
from django.shortcuts import get_object_or_404


class OrderDetailView(View):
    template_name = 'order_detail.html'

    def get(self, request, order_id):
        order = get_object_or_404(
            Order.objects.annotate(
                total_price=Coalesce(
                    Sum(
                        F('orderitem__quantity') * F('orderitem__product__price')
                    ),
                    Value(0),
                )
            ),
            id=order_id,
        )
        context = {
            'order': order,
        }
        return render(request, self.template_name, context)

在模板中,然后使用{{ order.total_price }}进行渲染.


Note:使用get_object_or_404(…) [Django-doc]通常更好, 然后直接使用.get(…) [Django-doc].在对象不存在的情况下, 例如,因为用户自己更改了URL,所以get_object_or_404(…)将返回HTTP 404 Not Found响应,而使用 .get(…)的结果是HTTP 500 Server Error.


Note:直接派生View类的子类化通常是not所必需的.在这种情况下,您的视图看起来像DetailView [Django-doc].通过使用DetailView而不是简单的View,您通常不必实现许多样板代码.

Python相关问答推荐

调查TensorFlow和PyTorch性能的差异

aiohTTP与pytest的奇怪行为

为什么使用SciPy中的Distance. cos函数比直接执行其Python代码更快?

如何判断. text文件中的某个字符,然后读取该行

两极:如何分割一个大 pyramid 并并行保存每个

在Transformer中使用LabelEncoding的ML模型管道

如果我已经使用了time,如何要求Python在12秒后执行另一个操作.sleep

这家einsum运营在做什么?E = NP.einsum(aj,kl-il,A,B)

如何在PIL、Python中对图像应用彩色面膜?

按照行主要蛇扫描顺序对点列表进行排序

理解Python的二分库:澄清bisect_left的使用

Pandas 在最近的日期合并,考虑到破产

使用FASTCGI在IIS上运行Django频道

需要计算60,000个坐标之间的距离

Pandas 都是(),但有一个门槛

如何从pandas的rame类继承并使用filepath实例化

从一个系列创建一个Dataframe,特别是如何重命名其中的列(例如:使用NAs/NaN)

如何在图中标记平均点?

提取相关行的最快方法—pandas

未调用自定义JSON编码器