Django ORM:多对多关联模型的用户ID过滤替代实现方法
筛选用户关联项目的其他实现方法
问题背景
现有Django的Project与User模型定义如下:
class Project(models.Model): name = models.CharField(max_length=100) content = models.TextField() creaters = models.ManyToManyField('User', related_name='creater_projects') workers = models.ManyToManyField('User', related_name='worker_projects') class User(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100)
需求是根据传入的user.id筛选该用户关联的Project数据,目前已经通过Q对象实现了该逻辑:
from django.db.models import Q user_id = 1 Project.objects.filter(Q(creaters__id=user_id) | Q(workers__id=user_id))
请问还有哪些可实现类似过滤效果的方法?
其他实现方法
1. 反向关联查询合并结果集
利用User模型的反向关联字段creater_projects和worker_projects,分别查询后合并结果,记得去重:
user = User.objects.get(id=1) # 合并两个QuerySet,调用distinct()去除重复项(用户可能同时是创建者和参与者) projects = (user.creater_projects.all() | user.worker_projects.all()).distinct()
2. 使用Exists子查询
通过Exists子查询分别判断用户是否属于项目的创建者或参与者列表:
from django.db.models import Exists, OuterRef user_id = 1 projects = Project.objects.filter( Exists(User.objects.filter(id=user_id, creater_projects=OuterRef('pk'))) | Exists(User.objects.filter(id=user_id, worker_projects=OuterRef('pk'))) )
这种写法和Q对象的性能表现相近,只是逻辑上更偏向子查询的思路。
3. 直接操作多对多中间表(不推荐)
Django会自动为多对多关系生成中间表,我们可以直接查询中间表获取关联的项目ID,再查询Project:
user_id = 1 # 获取用户作为创建者的项目ID集合 creater_project_ids = Project.creaters.through.objects.filter(user_id=user_id).values_list('project_id', flat=True) # 获取用户作为参与者的项目ID集合 worker_project_ids = Project.workers.through.objects.filter(user_id=user_id).values_list('project_id', flat=True) # 合并ID集合后查询项目 projects = Project.objects.filter(id__in=set(creater_project_ids) | set(worker_project_ids))
这种方法需要手动处理自动生成的中间表,代码可读性差,还容易因为模型变更出问题,除非有特殊场景需求,否则不建议使用。
内容的提问来源于stack exchange,提问作者Дмитрий
相关产品推荐
相关产品推荐

