Django ORM使用select_related做内连接返回异常结果如何解决
错误原因解析
- 第一个查询已经正确完成了内连接操作,你没有在
__dict__中看到MyBuffers表的字段,是因为__dict__仅会展示当前模型的本地存储字段,select_related预加载的关联表对象会作为实例属性缓存,不会直接出现在__dict__的第一层结果中。 - 第二个报错是因为
select_related仅支持传入关系型字段(外键、一对一关系)来指定要预加载的关联表,不能直接传入关联表的普通字段。你填写的projectid__radius中radius是MyBuffers的普通整数字段,不属于关系字段,因此触发字段类型错误。
正确使用方案
方案1:需要使用MyBuffers的多个字段
仅需要在select_related中指定外键字段名,即可预加载整张关联表,后续访问关联属性不会触发额外查询:
test = MyPoints.objects.select_related('projectid') # 直接通过关联属性取radius字段 print(test.first().projectid.radius)
方案2:仅需要radius单个字段
如果不需要整个MyBuffers对象,可以直接通过双下划线关联查询取指定字段,底层会自动执行内连接,内存开销更低:
# 仅获取所有radius值 radius_list = MyPoints.objects.values_list('projectid__radius', flat=True) # 同时获取MyPoints的字段和关联的radius point_info = MyPoints.objects.values('id', 'geog', 'projectid__radius')
可选优化建议
你当前的外键字段命名为projectid,容易和MyBuffers表的projectid字段混淆,建议修改外键的ORM层命名提升代码可读性,因为已经指定了db_column='projectid',修改不会影响数据库结构:
# MyPoints模型中外键字段修改为更语义化的名称 buffer = models.ForeignKey('MyBuffers', max_length=25, on_delete=models.DO_NOTHING, to_field='projectid', db_column='projectid')
修改后访问方式变为point.buffer.radius,语义更清晰,避免字段混淆。
内容的提问来源于stack exchange,提问作者iskandarblue
相关产品推荐
相关产品推荐

