【Django后端】微信小程序post请求返回403或者500的解决方案

单纯使用Django为微信小程序提供后端接口,我负责后端接口、同学负责前端,我们测试了get请求是没有问题的,但是在发送post请求时,前端收到的返回值一直是500和403。
PS:想直接看解决方法的可以点击下方的“解决方案”跳转过去

目录

  • 1.返回 500(服务器错误)
    • 1.1前端代码
    • 1.2后端接口
    • 1.3尝试的办法
      • 1.3.1修改前端 header
      • 1.3.2修改后端获取参数的方式
  • 2.返回 403(禁止访问,服务器收到请求,但拒绝提供服务)
    • 2.1尝试的办法
      • 2.1.1修改nginx相关配置
  • 3.解决方案
  • 4.总结

1.返回 500(服务器错误)

1.1前端代码

【Django后端】微信小程序post请求返回403或者500的解决方案_第1张图片

1.2后端接口

def get2(request):
    if request.method == "POST":
        id = request.POST.get('id')
        return HttpResponse({"result": id+5})

从上面的前端代码可以看得到,url的最后是没有加 / 的,其得到的返回值是500,然后我在后端接口把if语句删除,直接返回,但是前端的返回值依然不变,还是500。

1.3尝试的办法

1.3.1修改前端 header

在网上搜到一些资料,说是将前端代码的header修改:

header = {
	'content-type': 'application/x-www-form-urlencoded',
}

修改完以后仍然是错误的,返回值依然是500。

1.3.2修改后端获取参数的方式

看了很多资料以后,我感觉前端代码的写法没有问题,于是我认为是后端获取post请求的参数时出现了错误,我就尝试使用别的方式获取参数:

  • 第一种
def get2(request):
	req_data = self.request.body
	req_data = json.loads(req_data)
	id = req_data.get('id')
	return HttpResponse({"result": id+5})
  • 第二种
def get2(request):
	id = request.data['id']
	return HttpResponse({"result": id+5})

上述两种办法都不行,返回值依然是500,此时我感觉很奇怪,我就想看看这些请求发过来以后经历了什么。于是我将后端代码加了一句print语句,判断请求的类型:

def get2(request):
	print(request.method)
	id = request.POST.get('id')
	return HttpResponse({"result": id+5})

输出结果让我大吃一惊,因为它输出的是“GET”,那么请求的返回值是500就很容易理解了,因为我一直是使用获取POST请求参数的格式,所以服务就发生了错误返回500。然后我去查询请求的记录,我发现每一个POST请求的返回值都是301(也就是永久性重定向:本网页被永久性转移到另一个URL)。于是我去搜索原因,解决以后就出现了下面的问题。

2.返回 403(禁止访问,服务器收到请求,但拒绝提供服务)

通过前面的分析,我感觉事情很奇怪,因为每个POST请求都被永久性重定向了,查询了一些资料后我才了解到:django在url定向的时候,如果末尾不是‘/’,会被系统重定向到带‘/’的url,即301,然后空的请求被重定向,就变成了get。
如此我兴奋地让前端的同学把url最后面加上了 / ,但是一测试,返回值变成了403。

2.1尝试的办法

2.1.1修改nginx相关配置

因为部署django项目时是使用的nginx+uwsgi,在网上看到有人说nginx可能导致post请求返回403,搜了一些资料,感觉解决方法都比较麻烦,因此没有采用。(大家可以自行搜索一下)

3.解决方案

在搜索POST请求总是返回403时,偶然看到一个资料,其中提到这是一个跨域请求问题

(Django 中表单所需的 CSRF模板标签可防止跨站点请求伪造。CSRF使客户端浏览器访问过的恶意站点可以向您自己的服务器发出请求。因此,django 提供的 csrf_token 使您的 django服务器和站点可以轻松地免受此类恶意攻击。如果您的表单不受 csrf_token 保护,django 将返回 403禁止页面。这是对您网站的一种保护形式,尤其是在未故意遗漏令牌时。)

但是在某些情况下,django 站点不想使用 csrf_token 保护其表单,故Django提供了一个装饰器**@csrf_exempt**,此装饰器将视图标记为不受中间件确保的保护。
所以做出如下修改:

#在程序中导入csrf_exempt
from django.views.decorators.csrf import csrf_exempt
#在想接受POST请求的函数前面加上 @csrf_exempt
@csrf_exempt
def get2(request):
	print(request.method)
	id = request.POST.get('id')
	return HttpResponse({"result": id+5})

如此前端的请求就可以正常得到返回值了,返回状态为200。

4.总结

  • 前端的url需要以 / 结尾
  • 修改前端 ‘content-type’
header = {
	'content-type': 'application/x-www-form-urlencoded',
}
  • 后端接口函数前面加 @csrf_exempt
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def get2(request):
	print(request.method)
	id = request.POST.get('id')
	return HttpResponse({"result": id+5})

如果有不正确的地方请大家指正,感谢大家。

你可能感兴趣的:(后端开发,Python,django,后端,微信小程序,python,post)