Django ORM Annotate设置ForeignKey字段获取关联实例报错排查咨询
问题1:annotate生成的_user字段为int类型,无法访问username属性
原因
Django ORM的annotate机制直接映射SQL查询返回的标量结果,哪怕你指定output_field为ForeignKey类型,默认也只会返回关联表的主键值(整数),不会自动发起关联查询构造完整的User模型实例。
解决方案
可以先标注获取用户ID,再批量查询User实例绑定到Submission对象上,仅需2次查询即可实现需求,示例代码如下:
import django.db.models as djdm # 第一步:标注获取关联的用户ID qs = Submission.objects.annotate( _user_id = djdm.Subquery(rcm.RQCuser.objects.values('pk')[:1], output_field=djdm.IntegerField()) ) # 第二步:批量查询所有关联的User,构造ID到实例的映射 user_ids = qs.values_list('_user_id', flat=True).distinct() user_mapping = {user.pk: user for user in User.objects.filter(pk__in=user_ids)} # 第三步:将User实例绑定到对应Submission对象 for submission in qs: submission._user = user_mapping.get(submission._user_id) # 此时即可正常访问username属性 print(qs[0]._user.username)
问题2:AttributeError: 'ForeignKey' object has no attribute 'model'成因
正常定义在Django模型类中的ForeignKey字段,会在模型类初始化阶段由Django的元类自动注入model属性,指向该字段所属的模型类。
你手动临时实例化的myfk = djdm.ForeignKey(User, on_delete=djdm.DO_NOTHING)没有绑定到任何模型类,缺少上述自动初始化的过程,ORM在处理output_field时读取该属性就会抛出报错。
解决方案
无需手动创建ForeignKey实例作为output_field,直接使用IntegerField存储用户主键即可,参考问题1的示例代码即可规避该报错。
内容的提问来源于stack exchange,提问作者Lutz Prechelt
相关产品推荐
相关产品推荐

