Django 与数据库交互,你需要知道的 9 个技巧

本文介绍了 Django 开发中提高数据库交互效率的 9 个技巧,包括过滤器聚合、QuerySet 结果为 namedtuples、自定义函数、声明超时、限制查询、事务与锁控制、外键索引优化、组合索引列顺序和块范围索引。通过这些技巧,可以优化 ORM 默认行为,提升 Django 应用的性能。
摘要由CSDN通过智能技术生成

对开发人员来说,Django的ORM 确实非常实用,但是将数据库的访问抽象出来本身是有成本的,那些愿意在数据库中探索的开发人员,经常会发现修改 ORM 的默认行为可以带来性能的提升。在本文中,我将分享在 Django 中使用数据库的 9 个技巧。

1. 过滤器聚合(Aggregation with Filter)

在 Django 2.0 之前,如果我们想要得到诸如用户总数和活跃用户总数之类的东西,我们不得不求助于条件表达式:

from django.contrib.auth.models import User
from django.db.models import (
    Count,
    Sum,
    Case,
    When,
    Value,
    IntegerField,
)

User.objects.aggregate(
    total_users=Count('id'),
    total_active_users=Sum(Case(
        When(is_active=True, then=Value(1)),
        default=Value(0),
        output_field=IntegerField(),
    )),
)

在 Django 2.0 中,添加了聚合函数的过滤器参数,使其更容易:

from django.contrib.auth.models import User
from django.db.models import Count, F

User.objects.aggregate(
    total_users=Count('id'),
    total_active_users=Count('id', filter=F('is_active')),
)

很棒,又短又可口。如果你正在使用 PostgreSQL,这两个查询将如下所示:

SELECT
    COUNT(id) AS total_users,
    SUM(CASE WHEN is_active THEN 1 ELSE 0 END) AS total_active_users
FROM
    auth_users;
SELECT
    COUNT(id) AS total_users,
    COUNT(id) FILTER (WHERE is_active) AS total_active_users
FROM
    auth_users;

第二个查询使用了 WHERE 过滤子句。

2. 查询集的结果变为具名元组(QuerySet results as namedtuples)

我是一个 namedtuples 的粉丝,同时也是 Django 2.0 的 ORM 的粉丝。

在 Django 2.0 中,values_list 方法的参数中添加了一个叫做 named 的属性。将 named 设置为 True 会将 QuerySet 作为 namedtuples 列表返回:

> user.objects.values_list(
    'first_name',
    'last_name',
)[0]
(‘Haki’, ‘Benita’)
> user_names = User.objects.values_list(
    'first_name',
    'last_name',
    named=True,
)
> user_names[0]
Row(first_name='Haki', last_name='Benita')
> user_names[0].first_name
'Haki'
> user_names[0].last_name
'Benita'

3. 自定义函数(Custom functions)

Django 2.0 的 ORM 功能非常强大,而且特性丰富,但还是不能与所有数据库的特性同步。不过幸运的是,ORM让我们用自定义函数来扩展它。

假设我们有一个记录报告的持续时间字段,我们希望找到所有报告的平均持续时间:

from django.db.models import Avg
Report.objects.aggregate(avg_duration=Avg(‘duration’))
> {'avg_duration': datetime.timedelta(0, 0, 55432)}

那很棒,但是如果只有均值,信息量有点少。我们再算出标准偏差吧:

from django.db.models import Avg, Std
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值