如何在Django中通过一个查询从多个表中选择数据?

17 投票
4 回答
60252 浏览
提问于 2025-04-15 20:18

我有两个表,一个是“公司”,另一个是“员工”:

class Company(models.Model):
    name = models.CharField(max_length=60)

class Employee(models.Model):
    name = models.CharField(max_length=60)
    company = models.ForeignField(Company)

我想把每个员工列出来,并在旁边显示他们所属的公司。这个操作其实很简单,只需要用 employees = Employee.objects.all() 来获取所有员工,然后在模板中循环显示,调用 {{employee.company.name}} 就可以了。

不过,这样做有个问题,就是在循环中每处理一个员工,就会发起一个新的查询去查找对应的公司。也就是说,对于每个员工,都会向公司表发起一次查询,类似于这样:

SELECT `company`.`id`, `company`.`name`
FROM `company`
WHERE `company`.`id` = 1 # This will of course be the employee.company_id

我希望能在最开始就把员工和公司一起查询出来,而不是一个一个查。可以这样做:

SELECT `employee`.`name` AS `name`,
       `company`.`name` AS `company_name`
FROM `employee` INNER JOIN `company` ON `employee`.`company_id` = `company`.`id`

这样做在Django的查询集中可以实现吗?如果不行,有没有其他方法可以解决这个问题(不使用原始SQL)?或者说,这种情况可以忽略,缓存起来就算“优化”了吗?

4 个回答

10

我想你想要的功能是你查询集中的 select_related 方法。你可以查看 这个文档

select_related()

这个方法会返回一个查询集,它会自动“跟踪”外键关系,也就是说在执行查询的时候,它会选择额外的相关对象数据。这是一个性能提升的方式,虽然有时候查询会变得更大,但这样在后续使用外键关系时就不需要再去数据库查询了。

22

这是个老问题,我来给个新的回答。

其实,你可以这样做:

employees = Employee.objects.all().values('id','name','company__name')

这样一来,Django会自动查找Company这个类,并为你找到公司名称。

在模板页面上,使用{{employees.company__name}},这样就能正确显示公司名称了。

35

使用 select_related() 这个方法可以提前加载相关的属性:

Employee.objects.select_related()

撰写回答