【问题标题】:JSON object sent from Javascript to Django Views is empty从 Javascript 发送到 Django Views 的 JSON 对象为空
【发布时间】:2019-04-13 19:07:21
【问题描述】:

我正在尝试通过 ajax 将一些数据从 Javascript 发送到 Django。 这是我的 JS 代码:

            var json_name = {'name': 123}
            $.ajax({
            method: 'POST',
            url: 'my url',
            contentType: "application/json",
            headers: {
                    'Content-Type':'application/json',
                    'X-CSRFToken': "{{ csrf_token }}"
                },

            data: JSON.stringify(json_name),
            success: function (data) {
         //this gets called when server returns an OK response
            alert("it worked!");
            },
        error: function (data) {
             alert("it didnt work");
            }
        });

这是我的 Views.py:

def myview(request):
    if request.is_ajax():
       request_data = request.body
       # data = json.loads(request.body)
       print(request_data)
       # print(data)
       return render(request, 'candidate/view.html')
    else:
       return render(request, 'candidate/view.html')

我得到的输出是b''

当我尝试包含这些行时:

data = json.loads(request.body)
print(data)

我收到此错误:

TypeError: the JSON object must be str, not 'bytes'

我参考了here

有人可以帮我解决这个问题吗?如果您需要任何其他信息来解决此问题,我很乐意分享。

【问题讨论】:

  • json_name 在你的 JavaScript 中包含什么?在发送请求之前,您是否检查过它是否已按预期填充?
  • 是的,我在发送请求之前放了console.log(json_name),输出为:{name: 123}
  • 你是如何触发那个 Ajax 帖子的?是点击按钮吗?如果是这样,您是否致电preventDefault()?显示脚本的其余部分和 html?
  • 你试试 data = json.loads(request.body.decode('utf-8') print(data)

标签: javascript json ajax django


【解决方案1】:

我头上的头发掉了一半后,我用以下方法解决了:

views.py:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def myview(request):
if request.is_ajax():
    if request.method == 'POST':
        data = request.POST.get('senddata')
        print(data)
    return render(request, 'candidate/view.html')
else:
    return render(request, 'candidate/view.html')

我的 JS 代码:

            <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

            $.ajax({
            type: 'POST',
            url: 'my url',
            // contentType: "application/json",
            // headers: {
      //               'Content-Type':'application/json',
      //               'X-CSRFToken': "{{ csrf_token }}"
      //           },
            dataType: "json",
            data: {
                senddata: JSON.stringify(json_name),
                },

            // data: json_name,

            success: function (data) {
         //this gets called when server returns an OK response
            alert("it worked!");
            },
        error: function (data) {
             alert("it didnt work");
            }
        });

当我运行它时,它显示 it didnt work 但我可以在终端中看到输出,即数据已通过。

我尝试在 ajax 请求中包含 csrf 令牌,但失败了。因此,我在视图中使用了 csrf_exempt。

这可能是一种肮脏的做事方式,但它现在有效。如果有人有一个整洁和更好的答案,请在此处发布!

【讨论】:

    【解决方案2】:

    我已经使用 Python 3.6 和 Python 2.7 在 Django 1.11 上编写了一个基本测试用例。

    我一直在使用以下模板文件进行测试:

    <button>Send data</button>
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
    $('button').on('click', function(event) {
        var data = { name: 123 };
        $.ajax({
            method: 'POST',
            url: '',
            contentType: 'application/json',
            headers: {
                'X-CSRFToken': '{{ csrf_token }}',
            },
            data: JSON.stringify(data),
            success: function() {
                console.log('Success!');
            },
            error: function() {
                console.log('Error...');
            },
        });
    });
    </script>
    

    还有以下路由,它传递模板文件并打印任何 AJAX 数据:

    from django.http import response
    from django.shortcuts import render
    import json
    
    def index(request):
        if request.is_ajax():
            request_body = request.body
            data = json.loads(request_body)
            print(data)
        return render(request, 'stackoverflowhelp/index.html')
    

    我无法重现该问题。

    但是,经过更多研究,我发现 Python 3.6 中的 json.loads 方法支持 bytes 对象,而 documentation for Python 2.7 json.loads 表明它只支持字符串类型。虽然您发布的错误反映了这一点,但我已尝试使其产生与您看到的相同的错误,但没有成功。

    如您所见,我不必将该方法从 CSRF 保护中列入白名单。纯粹基于您提供的错误,在request.body 上调用decode 可能会起作用:

    def index(request):
        if request.is_ajax():
            request_body = request.body.decode("utf-8")
            data = json.loads(request_body)
            print(data)
        return render(request, 'stackoverflowhelp/index.html')
    

    【讨论】:

    • method: 'POST', url: 'my url', contentType: "application/json", headers: { 'Content-Type':'application/json', 'X-CSRFToken': "{{ csrf_token }}" }, datatype: "json", processData: false, data: json_name, 感谢您提供的信息,它让我对概念有了一些了解。但是,我仍然得到与b' ' 相同的输出。
    • 我看不出这个答案有什么意义。 OP 已经将数据转换为 JSON 字符串。 dataType 是服务器返回的数据,而不是发送的数据。
    • 你是对的,对不起。我以前见过这种问题,通常是因为 JQuery 将数据编码为查询字符串。我已经编写了一个测试用例,它似乎可以正确发送数据。我将用解决方案修改我的答案。
    猜你喜欢
    • 2015-07-07
    • 2014-07-08
    • 2016-01-09
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    相关资源
    最近更新 更多