Django使用ForeignKey关联3张表返回空值,求助解决方法
问题描述
尝试通过ForeignKey关联3张数据表,但查询返回空值。已使用select_related方法,也试过Insight.objects.all(),两种方式均无效。相关代码如下:
模型代码
class schedule(models.Model): login_id = models.CharField(primary_key=True,max_length=20) agent_name = models.CharField(max_length=100, blank=True, null=True) team = models.CharField(max_length=100, blank=True, null=True) class place_no(models.Model): place_id = models.CharField(max_length=50, blank=True, null=True) pc_no = models.CharField(max_length=50, blank=True, null=True) class Insight(models.Model): login_id = models.CharField(primary_key=True,max_length=20) place_id = models.CharField(max_length=50, blank=True, null=True) agent_name = models.ForeignKey( schedule, on_delete=models.CASCADE,blank=True, null=True ) pc_no = models.ForeignKey( place_no, on_delete=models.CASCADE,blank=True, null=True )
视图代码
def listings(request): data = Insight.objects.select_related('agent_name', 'pc_no') return render(request, 'pages/listings.html', {'data':data})
模板代码
{% for item in data %} <tr> <td class="text-center align-middle">{{ item.login_id }}</td> <td class="text-center align-middle">{{ item.place_id }}</td> <td class="text-center align-middle">{{ item.agent_name.agent_name }}</td> <td class="text-center align-middle">{{ item.pc_no.pc_no }}</td> </tr> {% endfor %}
问题分析与修复
核心问题
- 外键关联逻辑错位:Insight的
agent_name外键关联schedule模型,但字段名与关联模型内的字段重名,易混淆关联对象与字段值;同时Insight自身的place_id字段和pc_no外键无关联逻辑,无法匹配place_no表数据。 - place_no模型无有效主键:place_no未显式设置主键,Django自动生成的隐式id主键与Insight的关联逻辑不匹配,导致关联失效。
- 外键命名不规范:用业务字段名作为外键字段名,增加代码维护和排查难度。
修复后的代码
模型代码
# 遵循Django大驼峰模型命名惯例 class Schedule(models.Model): login_id = models.CharField(primary_key=True, max_length=20) agent_name = models.CharField(max_length=100, blank=True, null=True) team = models.CharField(max_length=100, blank=True, null=True) class PlaceNo(models.Model): # 将place_id设为主键,与Insight的关联逻辑对齐 place_id = models.CharField(primary_key=True, max_length=50) pc_no = models.CharField(max_length=50, blank=True, null=True) class Insight(models.Model): login_id = models.CharField(primary_key=True, max_length=20) # 重命名外键字段,明确关联对象 schedule = models.ForeignKey( Schedule, on_delete=models.CASCADE, blank=True, null=True, to_field='login_id' # 明确关联Schedule的主键login_id ) place = models.ForeignKey( PlaceNo, on_delete=models.CASCADE, blank=True, null=True, to_field='place_id' # 明确关联PlaceNo的主键place_id )
模板代码(对应修改字段名)
{% for item in data %} <tr> <td class="text-center align-middle">{{ item.login_id }}</td> <td class="text-center align-middle">{{ item.place.place_id }}</td> <td class="text-center align-middle">{{ item.schedule.agent_name }}</td> <td class="text-center align-middle">{{ item.place.pc_no }}</td> </tr> {% endfor %}
关键注意事项
- 确保Insight表中的
schedule_id(外键实际存储列)存储的是Schedule表中存在的login_id值,place_id存储的是PlaceNo表中存在的place_id值,否则关联查询仍会返回空。 - 视图中的
select_related可正常使用,修复后会正确预加载关联数据,避免N+1查询问题。
内容的提问来源于stack exchange,提问作者Islam Fahmy
相关产品推荐
相关产品推荐

