UrlGatewayLogin未返回HttpResponse对象,返回None问题求助
Hey there, let's break down exactly why you're seeing this error and how to fix it.
直接错误原因:返回了None而非合法的HttpResponse对象
Django 严格要求所有视图必须返回一个HttpResponse类(或其子类,比如render返回的TemplateResponse、HttpResponseBadRequest等),但你的代码在MyUser.DoesNotExist异常分支里直接返回了None:
try: user = MyUser.objects.get(token=token) except MyUser.DoesNotExist: return None # 这里就是问题所在!
当请求携带的token找不到对应的用户时,视图返回None,Django无法处理这个值,就会抛出UrlGatewayLogin didn't return an HttpResponse object错误。
隐藏的核心问题:token来源不匹配
更关键的是,你的登录逻辑和token生成逻辑是脱节的:
CustomObtainTokenView使用的是DRF自带的rest_framework.authtoken.models.Token模型来生成和存储token- 但
UrlGatewayLogin视图却在查询MyUser模型自己的token字段
这两个token是完全独立的!也就是说,你通过CustomObtainTokenView拿到的token,永远不会匹配MyUser.token字段的值,所以几乎每次请求都会触发MyUser.DoesNotExist异常,走到返回None的分支。
修复步骤
1. 先修复None返回的问题
把异常分支的return None替换成合法的HttpResponse,比如返回错误提示或错误页面:
from django.http import HttpResponseBadRequest # ... 其他代码 ... except MyUser.DoesNotExist: # 返回纯文本错误(适合API场景) return HttpResponseBadRequest("Invalid or expired token") # 或者返回自定义错误模板(适合网页场景) # return render(request, 'auth/invalid_token.html', status=400)
2. 统一token的存储与查询逻辑
推荐采用DRF官方的Token机制(更规范,无需自己维护token字段),修改UrlGatewayLogin视图查询DRF的Token模型:
from rest_framework.authtoken.models import Token from django.http import HttpResponseBadRequest class UrlGatewayLogin(View): def get(self, request, **kwargs): page_group = kwargs.get('page_group') token = request.GET.get('token') try: # 改为查询DRF的Token模型,通过token key找到关联用户 token_obj = Token.objects.get(key=token) user = token_obj.user except Token.DoesNotExist: return HttpResponseBadRequest("Invalid token") user.backend = 'django.contrib.auth.backends.ModelBackend' login(request, user) # 注意:render的第二个参数应该是模板文件名,比如'dashboard.html' return render(request, 'dashboard.html', {'page_group': page_group})
如果你坚持要使用MyUser模型的token字段,那需要修改CustomObtainTokenView,把生成的token保存到MyUser.token中:
from django.utils.timezone import utc from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.response import Response import datetime class CustomObtainTokenView(ObtainAuthToken): def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] # 生成新token并保存到MyUser字段 token_key = Token.generate_key() # 使用DRF的token生成方法 user.token = token_key user.save() return Response({ 'token': token_key, 'user_id': user.pk, 'email': user.email })
3. 额外注意点
确保render(request, 'dashboard', ...)中的第二个参数是正确的模板文件名(比如dashboard.html),否则会触发模板找不到的错误。
内容的提问来源于stack exchange,提问作者copser

