Django如何通过多模型关注对象列表过滤GenericForeignKey获取用户动态
问题原因
你之前的写法报错是因为GenericForeignKey是Django层面封装的虚拟字段,数据库中不存在对应的实际存储字段,无法直接使用actor__in这类跨关系查询语法,必须通过它绑定的两个实际数据库字段xxx_content_type和xxx_object_id来筛选。
实现代码
你可以将关注的对象按内容类型分组后拼接查询条件,一次性查出所有符合要求的动态:
from django.db.models import Q # 先按内容类型分组,存储所有关注对象的id follow_groups = {} for follow in thor.follow_set.all(): ct_id = follow.content_type_id if ct_id not in follow_groups: follow_groups[ct_id] = [] follow_groups[ct_id].append(follow.object_id) # 构造总查询条件 query = Q() for ct_id, obj_ids in follow_groups.items(): # 匹配:该对象作为活动的发起者 query |= Q(actor_content_type_id=ct_id, actor_object_id__in=obj_ids) # 匹配:该对象作为活动的作用目标 query |= Q(target_content_type_id=ct_id, target_object_id__in=obj_ids) # 执行查询,distinct去重,按id倒序就是按时间从新到旧排序 thor_activities = Activity.objects.filter(query).distinct().order_by('-id')
执行后得到的结果就包含你需要的三条动态。
优化方案(可选)
如果这个查询场景使用频率很高,可以封装为Activity模型的管理器方法,后续调用更简洁:
- 先定义自定义管理器
from django.db.models import Q, Manager class ActivityManager(Manager): def get_follow_activities_by_user(self, user): follow_groups = {} for follow in user.follow_set.all(): follow_groups.setdefault(follow.content_type_id, []).append(follow.object_id) query = Q() for ct_id, obj_ids in follow_groups.items(): query |= Q(actor_content_type_id=ct_id, actor_object_id__in=obj_ids) query |= Q(target_content_type_id=ct_id, target_object_id__in=obj_ids) return self.filter(query).distinct().order_by('-id')
- 给Activity模型绑定管理器
class Activity(models.Model): # 原有字段不变 objects = ActivityManager()
- 后续直接调用即可
thor_activities = Activity.objects.get_follow_activities_by_user(thor)
内容的提问来源于stack exchange,提问作者Msw Tm
相关产品推荐
相关产品推荐

