Django中如何筛选包含至少一名Worker的Branch实例及related_name用法咨询
嗨,我来帮你梳理下这个问题的解决思路~
首先先说说你设置的related_name:你现在给Worker的branch外键设置了related_name='branch',这个命名其实不太合理哦。related_name的作用是定义从Branch模型反向关联Worker实例的属性名,所以改成'workers'会更直观——这样之后你拿到一个Branch对象时,就能通过branch.workers.all()直接获取这个分支下的所有员工了。修改后的Worker模型字段应该是这样:
branch = models.ForeignKey(Branch, on_delete=models.SET_NULL, null=True, related_name='workers')
接下来是你最关心的:如何筛选出至少有一名Worker的Branch实例,这里有几种实用的方法:
方法一:利用反向关联的非空筛选
直接从Branch模型出发,过滤出存在关联Worker的记录,记得加distinct()避免重复结果(因为一个分支有多个员工时,未去重会返回多条相同的Branch实例):branches_with_workers = Branch.objects.filter(workers__isnull=False).distinct()方法二:结合annotate统计员工数量
用Count注解每个分支的员工数,再筛选数量大于0的分支,这种方法的好处是还能同时拿到每个分支的员工数量:from django.db.models import Count branches_with_workers = Branch.objects.annotate(worker_count=Count('workers')).filter(worker_count__gt=0)方法三:用Exists子查询(大数据量场景更高效)
如果你的数据量比较大,这种方法的性能会更好,它会通过子查询判断每个分支是否存在关联的Worker:from django.db.models import Exists, OuterRef branches_with_workers = Branch.objects.filter( Exists(Worker.objects.filter(branch=OuterRef('pk'))) )
另外你之前尝试的Worker.objects.filter(branch=?).exists(),这个写法是用来判断单个特定分支有没有员工的,没法直接拿到所有符合条件的分支列表,所以才会觉得“没意义”,换从Branch模型出发筛选就对啦~
备注:内容来源于stack exchange,提问作者Timur Arazmedov

