Django框架--ORM操作

1. 查询操作

1.1 filter()

用法

  • 用于过滤查询结果,返回符合条件的记录。
  • 支持链式调用。

示例

queryset = MyModel.objects.filter(field=value)

SQL 查询示例

SELECT * FROM MyModel WHERE field = value;

性能特点

  • 根据过滤条件生成 SQL 查询。
  • 支持复杂查询条件,性能取决于查询条件和索引。
1.2 exclude()

用法

  • 用于排除符合条件的记录。
  • 结果集为所有不符合条件的记录。

示例

queryset = MyModel.objects.exclude(field=value)

SQL 查询示例

SELECT * FROM MyModel WHERE field != value;

性能特点

  • 类似于 filter(),但条件是排除的。
  • 适用于排除某些不需要的记录。
1.3 get()

用法

  • 用于获取唯一的记录。如果查询条件匹配到多个记录,会引发 MultipleObjectsReturned 异常。

示例

obj = MyModel.objects.get(id=1)

SQL 查询示例

SELECT * FROM MyModel WHERE id = 1 LIMIT 1;

性能特点

  • 执行带有 LIMIT 1 的查询。
  • 适用于查找唯一记录。
1.4 aggregate()

用法

  • 用于对查询结果进行聚合操作,如计数、求和、平均值等。

示例

from django.db.models import Count, Sum

result = MyModel.objects.aggregate(total=Count('field'))

SQL 查询示例

SELECT COUNT(field) AS total FROM MyModel;

性能特点

  • 使用聚合函数进行计算,性能依赖于数据量和聚合函数。 只返回聚合结果,不包括具体的记录数据。
1.5 annotate()

用法

  • 用于给每个记录添加计算字段或聚合结果。

示例

from django.db.models import Count

queryset = MyModel.objects.annotate(num_related=Count('related_model'))

SQL 查询示例

SELECT MyModel.*, COUNT(RelatedModel.id) AS num_related
FROM MyModel
LEFT JOIN RelatedModel ON MyModel.id = RelatedModel.parent_model_id
GROUP BY MyModel.id;

性能特点

  • 添加计算字段,使用 LEFT JOIN 和聚合操作。 执行带有 GROUP BY 的查询,计算每个记录的聚合数据。
1.6 values()

用法

  • 返回一个包含字典的 QuerySet,每个字典代表一行数据。

示例

queryset = MyModel.objects.values('field1', 'field2')

SQL 查询示例

SELECT field1, field2 FROM MyModel;

性能特点

  • 只返回指定字段,减少数据传输量。
1.7 values_list()

用法

  • 返回一个包含元组的 QuerySet,每个元组代表一行数据。

示例

queryset = MyModel.objects.values_list('field1', 'field2')

SQL 查询示例

SELECT field1, field2 FROM MyModel;

性能特点

  • 返回元组数据,适合处理不需要字段名称的结果。

2. 更新操作

2.1 update()

用法

  • 用于批量更新符合条件的记录。

示例

MyModel.objects.filter(condition).update(field=value)

SQL 查询示例

UPDATE MyModel SET field = value WHERE condition;

性能特点

  • 高效的批量更新操作,不会触发 save() 方法。

3. 删除操作

3.1 delete()

用法

  • 用于删除符合条件的记录。删除操作会触发模型的 delete() 方法。

示例

MyModel.objects.filter(condition).delete()

SQL 查询示例

DELETE FROM MyModel WHERE condition;

性能特点

  • 删除操作会在数据库中实际删除记录,可能触发级联删除和信号处理。

4. 关联查询

4.1 select_related()

用法

  • 用于一对一和外键关系的优化查询,通过 INNER JOIN 一次性加载所有关联数据。

示例

queryset = MyModel.objects.select_related('related_model')

SQL 查询示例

SELECT MyModel.*, RelatedModel.*
FROM MyModel
INNER JOIN RelatedModel ON MyModel.related_model_id = RelatedModel.id;

性能特点

  • 高效减少数据库查询次数,但可能丢失主表记录(因 INNER JOIN)。
4.2 prefetch_related()

用法

  • 用于一对多和多对多关系的优化查询,通过多个查询在 Python 层面合并结果。

示例

queryset = MyModel.objects.prefetch_related('related_model')

SQL 查询示例

-- 第一个查询
SELECT * FROM MyModel;

-- 第二个查询
SELECT * FROM RelatedModel WHERE related_model_id IN (1, 2, 3, ...);

性能特点

  • 不丢失主表记录,适用于复杂关系,但可能增加查询时间和内存使用。
4.3 . 查询(点操作符)

用法

  • 用于通过点操作符访问外键字段。

示例

queryset = MyModel.objects.filter(related_model__field=value)

SQL 查询示例

SELECT * FROM MyModel
INNER JOIN RelatedModel ON MyModel.related_model_id = RelatedModel.id
WHERE RelatedModel.field = value;

性能特点

  • 主表记录仅在关联表中有匹配记录时才会返回,可能导致额外查询(N+1 问题)。

1:首先执行一个查询,从主表中获取数据(比如,获取 N 个对象)。

N:对于每个从主表返回的记录,再执行额外的查询去获取关联数据(比如,获取每个对象的外键关系的详细信息)。

books = Book.objects.all()

for book in books:

print(book.author.name)

解决 N+1 问题的常见方法是使用 select_related()(一对一或外键关系)和 prefetch_related()(多对多或反向外键关系)来减少数据库查询次数。

4.4 __ 查询(双下划线语法)

用法

  • 用于跨表字段查询,支持条件过滤和字段选择。

示例

queryset = MyModel.objects.filter(related_model__field=value).values('field')

SQL 查询示例

SELECT MyModel.field, RelatedModel.field
FROM MyModel
INNER JOIN RelatedModel ON MyModel.related_model_id = RelatedModel.id
WHERE RelatedModel.field = value;

性能特点

  • 支持复杂查询,但可能丢失主表记录(因 INNER JOIN),查询复杂性高。

总结与比较

  • 查询操作filter()exclude() 支持灵活的条件查询,get() 用于获取唯一记录,aggregate()annotate() 用于聚合和计算,values()values_list() 用于简化数据获取。
  • 更新操作update() 高效批量更新记录。
  • 删除操作delete() 删除记录并触发相关信号和级联删除。
  • 关联查询
    • select_related: 适用于一对一和外键关系,通过 INNER JOIN 加载数据,丢失主表记录的风险。
    • prefetch_related: 适用于一对多和多对多关系,通过多个查询加载数据,确保主表记录。
    • . 查询: 通过点操作符访问外键字段,可能导致额外查询(N+1 问题)。
    • __ 查询: 支持复杂的跨表查询,使用 INNER JOIN,主表记录可能丢失。
posted @   脑袋凉凉  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示