📌  相关文章
📜  构建 Django 应用程序时应避免的 7 个错误(1)

📅  最后修改于: 2023-12-03 15:40:21.766000             🧑  作者: Mango

构建 Django 应用程序时应避免的 7 个错误

Django 是一个流行的 Web 应用程序框架,使用其可以快速开发高质量的 Web 应用程序。在使用 Django 进行应用程序开发时,有一些常见的错误需要避免,以确保实现可维护、可扩展和高效的应用程序。

以下是构建 Django 应用程序时应避免的 7 个错误:

1. 使用数据库查询时未使用缓存

查询数据库是 Django 应用程序中常见的任务之一。如果没有正确地使用缓存,重复查询可能会导致应用程序的性能下降。

from django.core.cache import cache

# Bad example
def get_user(id):
    return User.objects.get(id=id)

# Good example, uses cache
def get_user(id):
    key = f"user_{id}"
    user = cache.get(key)
    if user is None:
        user = User.objects.get(id=id)
        cache.set(key, user, timeout=60)
    return user
2. 在模板中执行查询操作

在 Django 模板中执行查询操作会使应用程序性能下降。在 Django 模板中执行查询操作的行为称为“数据库查询暴露”。

<!-- Bad example -->
{% for product in Product.objects.all %}
    <div>{{ product.name }}</div>
{% endfor %}

<!-- Good example, pass query result from view -->
<!-- Views.py -->
def product_list(request):
    products = Product.objects.all()
    return render(request, 'product_list.html', {
        'products': products
    })

<!-- Product_list.html -->
{% for product in products %}
    <div>{{ product.name }}</div>
{% endfor %}
3. 在循环中执行查询操作

在循环中多次执行查询操作会导致大量查询,并且可能会使应用程序的性能下降。

# Bad example
def get_products(price):
    products = []
    for category in Category.objects.all():
        for product in Product.objects.filter(category=category, price=price):
            products.append(product)
    return products

# Good example, use prefetch_related
def get_products(price):
    categories = Category.objects.prefetch_related('products').all()
    return [product for category in categories for product in category.products.filter(price=price)]
4. 不使用标记缓存的模板片段

Django 提供了模板片段,使得可以将常用的页面部分缓存在缓存中来提高性能。 如果没有正确地使用缓存,可能会导致应用程序的性能下降。

<!-- Bad example -->
{% for product in Product.objects.all %}
    <div>{{ product.name }}</div>
{% endfor %}

<!-- Good example, use cache with fragment name -->
{% load cache %}
{% cache 600 "product_list" %}
    {% for product in Product.objects.all %}
        <div>{{ product.name }}</div>
    {% endfor %}
{% endcache %}
5. 不使用添加到 INSTALLED_APPS 中的应用程序中的模板

当你想使用某个应用程序中的模板时,可以在该应用程序的 templates 目录中使用 {% include %} 模板标记。 这样是错误的,因为在 % include % 中指定的所有相对路径都在包含它的模板的目录中搜索。

# Bad example, include template from wrong directory
{% include 'myapp/templates/mytemplate.html' %}
# Good example, include template from correct directory
{% include 'myapp/mytemplate.html' %}
6. 从函数返回上下文时忘记转换为字典

在视图函数中,必须将上下文对象作为 HttpResponse 对象的参数返回。向 HttpResponse 对象传递的上下文必须是字典对象。

# Bad example
def my_view(request):
    context = {'message': 'Hello, World!'}
    return render(request, 'my_template.html', context)

# Good example, context is dict
def my_view(request):
    context = {'message': 'Hello, World!'}
    return render(request, 'my_template.html', context=context)
7. 在模型定义或管理器上使用同步代码

当你需要执行长时间的或需要大量计算的任务时,你需要使用异步编程。 不要在同步代码上使用大量计算或网络 I/O,而是使用异步编程。

# Bad example, synchronous code
class MyModel(models.Model):
    ...
    @classmethod
    def do_long_task(cls):
        # This task takes a long time to run
        ...

# Good example, asynchronous code
class MyModel(models.Model):
    ...
    @classmethod
    async def do_long_task(cls):
        # This task takes a long time to run
        ...