Django视图跳转异常:无Kcal实例时进入详情页仍报错
问题排查与解决
核心错误原因
当用户未关联Kcal实例时,直接访问self.request.user.kcal会触发DoesNotExist异常(即你看到的“User has no kcal.”错误),而非返回False或None。这是Django OneToOneField反向关联的默认行为:关联不存在时直接访问会抛出异常,导致你的dispatch方法里的跳转逻辑根本无法执行。
修复方案
1. 修复存在性判断逻辑
修改dispatch方法的判断逻辑,改用hasattr检查用户是否有kcal关联,避免直接访问触发异常:
class KcalDetailView(DetailView): model = User context_object_name = 'target_kcal' template_name = 'kcalculatorapp/detail.html' def dispatch(self, request, *args, **kwargs): # 使用hasattr判断是否存在关联的Kcal实例 if not hasattr(request.user, 'kcal'): return HttpResponseRedirect(reverse('kcalculatorapp:create')) return super(KcalDetailView, self).dispatch(request, *args, **kwargs)
或者用try-except块捕获异常:
def dispatch(self, request, *args, **kwargs): try: # 尝试访问关联实例,不存在则触发异常 _ = request.user.kcal except Kcal.DoesNotExist: return HttpResponseRedirect(reverse('kcalculatorapp:create')) return super(KcalDetailView, self).dispatch(request, *args, **kwargs)
2. 优化DetailView配置(可选但推荐)
当前你的DetailView绑定的模型是User,但实际要展示的是Kcal详情,逻辑不符。建议将模型改为Kcal,并通过get_object直接获取当前用户的Kcal实例:
class KcalDetailView(DetailView): model = Kcal context_object_name = 'target_kcal' template_name = 'kcalculatorapp/detail.html' def dispatch(self, request, *args, **kwargs): if not hasattr(request.user, 'kcal'): return HttpResponseRedirect(reverse('kcalculatorapp:create')) return super().dispatch(request, *args, **kwargs) def get_object(self, queryset=None): # 直接返回当前用户关联的Kcal实例 return self.request.user.kcal
3. 修复模型字段潜在问题
你的Kcal模型中,height、weight、age是PositiveIntegerField,但设置了default=''(空字符串),这会导致创建实例时类型错误(字符串无法转为整数)。建议移除无效的default值:
class Kcal(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='kcal', null=True) height = models.PositiveIntegerField(null=False, verbose_name='height') weight = models.PositiveIntegerField(null=False, verbose_name='weight') age = models.PositiveIntegerField(null=False, verbose_name='age') created_at = models.DateField(auto_now_add=True, null=True)
内容的提问来源于stack exchange,提问作者Corgi coding
相关产品推荐
相关产品推荐

