Django中能否使用annotate为关联模型字段添加自定义注解
Django ORM annotate 关联模型自定义属性问题解答
问题描述
请问如下操作是否可以实现?希望在使用Django ORM查询时,通过annotate方法为关联模型字段设置自定义值,在通过select_related加载关联对象后,可直接访问该关联对象上的对应注解属性,示例代码如下:
m = Message.objects.annotate(room__something=Value('DOH', output_field=CharField())).select_related('room') m.room.something == 'DOH' # is true
结论
目前原生Django ORM暂不支持该写法。
Django的annotate方法默认只会将注解字段挂载到当前查询的主模型实例上,不会自动将双下划线指定的关联模型字段注入到select_related加载的关联对象实例中。
替代实现方案
- 方案1:手动中转赋值
查询时先将注解字段挂载到主模型上,后续手动赋值到关联对象即可:# 查询时给主模型加注解字段 messages = Message.objects.annotate( _room_something=Value('DOH', output_field=CharField()) ).select_related('room') # 手动赋值到关联对象 for msg in messages: msg.room.something = msg._room_something # 后续即可直接访问 print(msg.room.something) # 输出 DOH - 方案2:从关联模型侧发起查询
如果业务逻辑允许,可以直接从关联模型(示例中为Room)侧做annotate,再通过反向关联拿到主模型数据:# 直接给Room模型加注解,反向预加载关联的Message rooms = Room.objects.annotate( something=Value('DOH', output_field=CharField()) ).prefetch_related('message_set') # 直接访问注解属性 for room in rooms: print(room.something) # 输出 DOH # 遍历关联的Message处理业务逻辑 for msg in room.message_set.all(): pass - 方案3:封装查询逻辑简化操作
如果需要频繁使用该能力,可以自定义QuerySet方法封装手动赋值的逻辑,不需要每次查询重复写赋值代码。
补充说明
你提交的该功能增强请求目前还未被Django官方合入,后续版本有可能支持该特性,可关注官方版本更新日志。
内容的提问来源于stack exchange,提问作者user1849962
相关产品推荐
相关产品推荐

