Django DetailView查询关联Trainee时报id字段预期数值却得到DeferredAttribute错误
问题排查结果
问题原因
你调用了self.model.id获取培训ID,self.model指向的是NewHireTraining模型类本身,并非当前请求对应的已加载数据的实例。类层面的id属性是Django ORM的DeferredAttribute描述符对象,不是具体的ID数值,因此传递给过滤条件时会触发类型错误。
修复方案
DetailView在执行get_context_data前已经完成了当前培训实例的查询,你可以通过self.object直接获取到当前请求对应的NewHireTraining实例,替换过滤条件即可:
class TrainingDetailsView(DetailView): model = NewHireTraining template_name = 'nht/training_details.html' context_object_name = 'training' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 将self.model.id替换为self.object.id context['trainees'] = Trainee.objects.filter(new_hire_training = self.object.id) return context
更简洁的优化写法
你可以直接利用Django外键自动生成的反向关联管理器获取学员数据,不需要手动编写过滤逻辑:
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 直接通过反向关系取关联的所有学员 context['trainees'] = self.object.trainee_set.all() return context
如果觉得默认的trainee_set命名不够直观,你可以在定义外键时添加related_name参数自定义反向关联名:
# models.py中修改Trainee的外键定义 new_hire_training = models.ForeignKey(NewHireTraining, on_delete=models.CASCADE, default="", related_name="trainees")
修改后就可以直接用更语义化的写法:context['trainees'] = self.object.trainees.all()
内容的提问来源于stack exchange,提问作者ivan corniel
相关产品推荐
相关产品推荐

