Django ORM小记

对一些常用的小技巧记录。

select_for_update

select_for_update 可以做小并发的控制,其只能在事务中使用。符合条件的查询结果会被加锁,其他查询包含加锁的数据时会阻塞,直到事务完成,如果其他查询结果不包含加锁的记录则不受影响。

1
2
3
4
5
6
7
from django.db import transaction

with transaction.atomic():
# 会给所有type = '1' 的记录加锁
tickets = Ticket.objects.select_for_update().filter(type='1')
# 单条记录加锁
ticket = Ticket.objects.select_for_update().get(id=12)

select_related 在查询时通过外键关系将关联的对象一起查询出来,从而避免查询查询以优化查询性能,适合一对一/一对多关系或关联表数据量比较小的情况。

1
Person.objects.select_related('cls')

对应执行的sql语句

1
SELECT `persons`.`id`, `persons`.`name`, `classes`.`id`, `classes`.`name` ... FROM `persons` LEFT OUTER JOIN `classes` ON (`persons`.`cls_id` = `classes`.`id`)

prefetch_related 一样可以用于优化查询性能,但实现方式与select_related不同,其会产生两条sql语句,查询结果会被缓存到内存中,然后进行合并,适合对多关系或关联表数据量比较大的情况。

1
Person.objects.prefetch_related('cls')

对应执行的两条sql语句

1
2
SELECT `persons`.`id`, `persons`.`name` ... FROM `persons`;
SELECT `classes`.`id`, `classes`.`name` ... FROM `classes` WHERE `classes`.`id` IN (2, 3)';