Django 跨域问题 (request.POST 获得为空)

最近接触了Python中的Django框架,建立了一个以Django为后端,vue 作为前端的web框架。在测试vue与Django前后端交互的时候遇到了获取request.body或者request.POST.data 获取为空的情况。记录一下自己的解决方法。

同源策略

同源是指"协议+域名+端口"三者相同,只要三者之间有一项不同,就不算是同源。这里介绍的就是不同端口之间的数据交互问题。

跨域问题

简而言之,为了避免浏览器受到XSS,CSFR等攻击,不同源的服务进程之间无法直接进行数据交互。

代理

要解决不同源问题,需要设置代理,使二者资源可以相互访问。我们可以选择在前端或者后端设置代理,最好是都设置代理。

前端

在vue项目中的config/index.js文件加入以下代理来设置代理,如果没有此文件我们可以在根目录下建立一个vue.confg.js 文件来加入

module.exports = {
  lintOnSave: false,
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        ws: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}
  1. /api 表示 '/api’下面包含的路径都需要代理
  2. target 表示 代理的目标服务器地址
  3. changeOrigin 表示是否修改请求的源地址
  4. pathRewrite:路径覆盖,将 ‘^/api’替换为’’

后端

最简单的一种方法是引入django-cors-headers(Django中)

pip install django-cors-headers

配置setting.py 文件,在里面加入下面的代码(前两项是添加到相应位置里)

INSTALLED_APPS = [
    'corsheaders',
]


MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]


CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = (
    ['http://127.0.0.1:*']
)
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    'X_FILENAME',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'Pragma',
)

下面为 views.py 中的文件,采用的是restful 风格,采用了 Django rest-framework 框架,没接触也问题不大,我们只需要拿到request 的数据就行

我们需要在函数之前加上 @csrf_exempt

class BookViewSet(ModelViewSet):
    parser_classes = [JSONParser, FormParser]
    """视图集"""
    queryset = models.BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # books/pk/createBook/
    @action(methods=['post'], detail=True)
    @csrf_exempt
    def createBook(self, request, pk):
        print(request.body)
        serializer = UserInfoSerializer(data=json.loads(request.body.decode('utf8')))
        if serializer.is_valid():
            serializer.save() # 存入数据库
            return JsonResponse({
                'code': 2000,
                'msg': '创建成功',
                'data': 'algorithm'
            })
        else:
            return JsonResponse({
                'code': 2010,
                'msg': '创建失败',
                'data': 'algorithm'
            })

我们现在使用postman发送post请求,里面实现的createBook方法就是用来获取发送到的post请求,获取post数据,并存入数据库。

下面标出了发送时的具体选择。
Django 跨域问题 (request.POST 获得为空)_第1张图片

打印的request.body如下

b'{\r\n    "url" : "localhost",\r\n    "name" : "\xe5\xb0\x8f\xe7\x8e\x8b\xe5\xad\x90"\r\n}'

你可能感兴趣的:(python,前后端开发,vue,django,python)