You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django登录接口POST请求持续返回400错误,求有效调试方案

问题诊断与解决方案

首先,你的400 Bad Request错误核心原因是请求格式不匹配:

你的SignInView中使用json.loads(request.body)来解析请求数据,但你用Httpie发送的默认请求是application/x-www-form-urlencoded格式(表单格式),而不是JSON格式。这会导致json.loads解析失败,触发异常,最终返回400错误。

快速修复方案

方案1:修改Httpie请求,发送JSON格式

用Httpie发送JSON请求,需要明确指定Content-Type,或者直接传递JSON字符串:

# 方式1:自动生成JSON
http -v POST http://127.0.0.1:8000/account/signin username='aaron' password='1234' Content-Type:application/json

# 方式2:直接传递JSON字符串
http -v POST http://127.0.0.1:8000/account/signin '{"username":"aaron","password":"1234"}'

方案2:修改Django视图,兼容表单数据

如果希望支持多种请求格式,可以在视图中同时处理JSON和表单数据:

class SignInView(View):
    def post(self, request):
        try:
            # 先尝试解析JSON
            data = json.loads(request.body)
        except json.JSONDecodeError:
            # 解析失败则尝试表单数据
            data = request.POST.dict()
        
        try:
            # 后续登录逻辑不变
            query = Q(email=data.get('email')) | Q(username=data.get('username')) | Q(fullname=data.get('fullname'))
            if Account.objects.filter(query).exists():
                account = Account.objects.get(query)
                encoded_pw = account.password.encode('utf-8')
                encoded_input = data['password'].encode('utf-8')
                if bcrypt.checkpw(encoded_input, encoded_pw):
                    token = jwt.encode({ 'email' : account.email }, 'secret', algorithm='HS256').decode('utf-8')
                    return JsonResponse({ 'access_token' : token }, status=200)
                return HttpResponse(status=403)
            return HttpResponse(status=402)
        except KeyError:
            return JsonResponse({"message": "INVALID_KEYS"}, status=400)
        except Account.MultipleObjectsReturned:
            return JsonResponse({"message": "DUPLICATE_ACCOUNTS"}, status=400)

除了pdb和print的调试方法

  1. Django Debug Toolbar
    安装后,它会在页面底部显示请求详情,包括请求头、POST数据、异常栈、数据库查询等,能直观看到请求是否被正确解析。

  2. 日志记录
    在settings.py中配置日志,将请求和异常信息写入文件,方便事后排查:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'debug_file': {
                'level': 'DEBUG',
                'class': 'logging.FileHandler',
                'filename': './debug.log',
            },
        },
        'loggers': {
            'django.request': {
                'handlers': ['debug_file'],
                'level': 'DEBUG',
                'propagate': True,
            },
        },
    }
    

    这样所有请求相关的异常和细节都会被记录到debug.log中。

  3. 返回原始请求信息
    在视图开头临时添加代码,返回请求的原始内容和类型,快速定位格式问题:

    class SignInView(View):
        def post(self, request):
            # 临时调试:返回请求详情
            return JsonResponse({
                'raw_body': request.body.decode('utf-8'),
                'content_type': request.META.get('CONTENT_TYPE'),
                'post_data': request.POST.dict()
            })
            # 后续代码...
    
  4. 使用Postman/Insomnia等可视化工具
    这类工具可以直观地选择请求格式(JSON/表单),查看请求头和响应详情,比命令行更容易排查格式问题。

  5. 捕获更细粒度的异常
    除了KeyError,还要捕获JSONDecodeError和MultipleObjectsReturned等异常,返回更明确的错误信息:

    import json
    from django.core.exceptions import MultipleObjectsReturned
    
    class SignInView(View):
        def post(self, request):
            try:
                data = json.loads(request.body)
            except json.JSONDecodeError:
                return JsonResponse({"message": "INVALID_JSON_FORMAT"}, status=400)
            
            try:
                # 登录逻辑...
            except KeyError:
                return JsonResponse({"message": "INVALID_KEYS"}, status=400)
            except MultipleObjectsReturned:
                return JsonResponse({"message": "MULTIPLE_ACCOUNTS_MATCH"}, status=400)
    

额外优化建议

  • 你的Account.objects.get(...)可能会抛出MultipleObjectsReturned异常(比如多个用户有相同的fullname),必须捕获这个异常,避免服务器返回500错误。
  • 考虑使用Django自带的AbstractBaseUser和AuthenticationBackend来实现自定义认证,这样能更好地利用Django的认证系统,减少重复代码。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:02:55