Python中Django ORM常见问题与解决方案
写单元测试遇到的,搜索搜不到答案,因为关键词不对
一个 orm 对象 如 user 我在其他地方修改了数据库
现在该如何使 user 对象更新到数据库的最新情况
Python中Django ORM常见问题与解决方案
比如你把 User 对象的 name 修改成了新的名字叫 yuan
User.update(name=“yuan”)
帖子标题是“Python中Django ORM常见问题与解决方案”。这是一个不涉及具体代码示例的通用问题,因此我将提供简洁、精炼的答案,直接回答核心。
Django ORM常见问题主要集中在查询性能、复杂查询构建以及模型关系管理上。
-
N+1查询问题:这是最典型的性能瓶颈。当你遍历一个查询集(QuerySet),并在循环中访问每个对象的外键或一对一关系时,ORM会为每个对象单独发起一次数据库查询。解决方案是使用
select_related()(用于外键和一对一关系,进行SQL JOIN)和prefetch_related()(用于多对多和反向一对多关系,进行额外的查询并在Python中进行“连接”)。 -
复杂查询与Q/F对象:当过滤条件需要复杂的OR逻辑,或者需要基于模型字段值进行操作时,简单的
filter()可能不够用。Q对象用于构建复杂的查询条件(如|(OR),&(AND),~(NOT))。F对象则用于在查询中引用模型的字段值,实现基于字段的更新或比较,避免竞争条件。 -
聚合与注解(Aggregation & Annotation):需要对查询结果进行分组统计或为每个对象添加计算字段时,需要使用
aggregate()(返回整个查询集的汇总字典)和annotate()(为查询集中的每个对象添加一个计算出的字段)。 -
查询集(QuerySet)的惰性与缓存:理解QuerySet是惰性的至关重要。创建QuerySet不会立即访问数据库,只有在“求值”(如迭代、切片、序列化、调用
len()或list())时才会执行查询。同时,对同一个已求值的QuerySet进行重复访问会使用其缓存,但要注意过滤条件会生成新的QuerySet并重新查询。 -
模型关系与
related_name:在定义ForeignKey或ManyToManyField时,设置一个清晰的related_name非常重要。它是从相关对象反向访问本模型的关系管理器名称。如果省略,Django会自动生成(如foo_set),但在模型关系复杂时,自定义的related_name能让代码更清晰、更不易冲突。
总结建议: 掌握 select_related/prefetch_related、Q/F对象以及理解QuerySet的惰性是高效使用Django ORM的关键。
#1 我已经在其他地方更新,数据已经是 name=yuan 了
可是我当前这个 user 对象的 name 还是没变
我想要这个 user 对象根据数据库把 name 变成 yuan
重新从数据库读一遍呗。。。
user.refresh_from_db()
这个问题在工作场景遇到过,异步多次请求,后请求完成修改的时候总会把之前修改的覆盖掉,经过研究发现,orm 中 obj.save()会覆盖字段内容,使用 queryset.update 则只更新要更新的字段内容,其他字段保留数据库中当前最新内容不会覆盖
所以,用 User.objects.filter(user_object.pk)拿到 user 对象的 queryset,然后 queryset .update 就好了,可以封装一下再加上一些字段处理方便使用,不再用。object.save()覆盖已修改内容的烦恼


