Django中select_related未返回关联表数据的原因咨询
问题原因
select_related('badge')的作用是执行SQL JOIN查询,把Requirement和关联的Badge数据一次性拉取出来,避免后续访问关联对象时触发额外数据库请求,但它不会自动让values()返回关联模型的字段。
values()默认只返回当前查询模型(这里是Requirement)的字段,要包含Badge的字段,必须显式指定,格式为关联外键名__字段名。
解决方案
修改视图中的查询代码,明确列出需要的字段:
def get_requirements(request): requirements = Requirement.objects.all().select_related('badge').values( # Requirement表字段 'id', 'number', 'name', 'description', # Badge表字段,用badge__前缀 'badge__id', 'badge__level', 'badge__name', 'badge__description' ) return JsonResponse(list(requirements), safe=False)
如果想自动获取两张表的所有字段,可以动态生成字段列表:
from django.db.models.fields import Field def get_requirements(request): # 获取Requirement的所有字段名 req_fields = [field.name for field in Requirement._meta.get_fields() if isinstance(field, Field)] # 获取Badge的所有字段名,加上badge__前缀 badge_fields = [f'badge__{field.name}' for field in Badge._meta.get_fields() if isinstance(field, Field)] requirements = Requirement.objects.all().select_related('badge').values(*req_fields + badge_fields) return JsonResponse(list(requirements), safe=False)
额外说明
- 别删掉
select_related('badge'),它能保证只执行一次数据库查询,避免多次请求的性能问题。 - 返回的JSON里,Badge的字段会是
badge__id这种格式的键,要是觉得别扭,也可以用annotate重命名字段,比如annotate(badge_name=F('badge__name')),这样返回的键就是badge_name了。
内容的提问来源于stack exchange,提问作者nightwingSL
相关产品推荐
相关产品推荐

