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

使用Django视图调用POST接口报400错误求助

问题:Django视图调用POST接口时QueryDict为空返回400错误

我在使用Django视图调用POST接口时碰到了400错误,之前还遇到过CSRF禁用问题,现在临时用@csrf_exempt注解处理。现在出现一个奇怪的情况:

  • 直接调用API时,POST参数能正常被接收(QueryDict有值),返回200状态码;
  • 但通过Django视图调用这个API时,API接收到的QueryDict是空的,返回400错误。

相关日志

直接调用API日志

QueryDict: {'book': ['Second '], 'author': ['Ban'], 'date': ['2018-01-10 08:00AM']} [22/Jan/2018 18:56:09] "POST /api/test/ HTTP/1.1" 200 61

通过视图调用API日志

QueryDict: {} [22/Jan/2018 18:56:12] "POST /api/test/?book=Second+&author=Ban&date=2018-01-10+08%3A00AM HTTP/1.1" 400 36
[22/Jan/2018 18:56:12] "POST /test/ HTTP/1.1" 200 19

相关代码

models.py

class TestPost(models.Model):
    book = models.CharField(max_length=10, blank=True, null=True)
    author = models.CharField(max_length=10, blank=True, null=True)
    date = models.DateTimeField(blank=True, null=True)

serializer.py

class TestPostSerializer(serializers.ModelSerializer):
    date = serializers.DateTimeField(format="%Y-%m-%d %I:%M %p")
    class Meta:
        model = TestPost
        fields = ('id', 'book', 'author', 'date')

views.py

from django.http import HttpResponse
import requests

def my_django_view(request):
    if request.method == 'POST':
        r = requests.post('http://127.0.0.1:8000/api/test/', params=request.POST)
    else:
        r = requests.get('http://127.0.0.1:8000/api/test/', params=request.GET)
    if r.status_code == 200:
        return HttpResponse('Yay, it worked')
    return HttpResponse('Could not save data')

class TestPostViewSet(viewsets.ModelViewSet):
    permission_classes = [AllowAny]
    queryset = TestPost.objects.all()
    serializer_class = TestPostSerializer

问题原因与解决方案

兄弟,这问题我一眼就瞅出来了!你在my_django_view里调用requests.post的时候用了params=request.POST,这完全用错参数了啊!

params是用来把数据塞到URL的查询字符串里的(就是GET请求那种?key=value的形式),但POST请求的参数应该放到请求体里,得用data参数才行!你看日志里通过视图调用的那条,URL后面跟着一堆book=Second+&author=Ban...,这说明你把本该放在请求体里的POST参数全塞到URL里了,而你的API接口是期望从请求体拿POST数据的,自然就拿到空的QueryDict,返回400错误了。

修正后的代码

把my_django_view里的params改成data就搞定了:

def my_django_view(request):
    if request.method == 'POST':
        # 把params换成data,让POST数据进入请求体
        r = requests.post('http://127.0.0.1:8000/api/test/', data=request.POST)
    else:
        r = requests.get('http://127.0.0.1:8000/api/test/', params=request.GET)
    if r.status_code == 200:
        return HttpResponse('Yay, it worked')
    return HttpResponse('Could not save data')

另外提个小建议:@csrf_exempt只是临时救急的方案,正式环境里最好还是正确处理CSRF验证,比如在请求里带上CSRF token,这样更安全。

内容的提问来源于stack exchange,提问作者Jin Nii Sama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:01:43