【问题标题】:Django view returns None during Ajax requestDjango 视图在 Ajax 请求期间返回 None
【发布时间】:2020-12-10 14:47:50
【问题描述】:

我有一个 Django Web 应用程序,我正在尝试进行 ajax 调用以上传大图像。如果我可以上传我要上传的图像,我将使用 pythonocc 库读取图像并返回卷信息。由于这个过程需要很长时间,我正在尝试使用 django-background-tasks 库来完成。根据我所说的,我试图获取图像并将其发送到视图的ajax请求如下。

var data = new FormData();
var img = $('#id_Volume')[0].files[0];
data.append('img', img);
data.append('csrfmiddlewaretoken', '{{ csrf_token }}');
$.ajax({
  method: 'POST',
  url: '{% url 'data:upload' %}',
  cache: false,
  processData: false,
  contentType: false,
  type: 'POST',
  data: data,
}).done(function(data) {
});

我的观点在 Ajax 请求后将起作用;

def uploadFile(request):
    if request.method == 'POST':
        file = request.FILES.get('img')
        filename = file.name
        key = 'media/' + filename
        s3_resource = boto3.resource('s3')
        bucket = s3_resource.Bucket('bucket')
        bucket.put_object(Key=key, Body=file)
        new_data = Data(author=request.user)
        new_data.save()
        data_id = new_data.id
        initial = CompletedTask.objects.filter(verbose_name=verbose)
        request.session['u_initial'] = len(initial)
        verbose = str(request.user) + '_3D'
        read_3D(data_id, key, filename, verbose_name = verbose) ###background-task function is called
        return redirect('data:uploadStatus')

调用这个后台任务函数的视图也应该重定向视图,这将显示上传的状态。

def upload_status(request):
    customer= str(request.user)
    verbose = customer + '_3D'
    initial = request.session['u_initial']
    if request.is_ajax():
        running, completed = get_upload_status(verbose)
        context = {
        "initial": initial,
        "running": running,
        "completed": completed,
        }
        return JsonResponse(context)
    return render(request, "file_pending.html")

但是,当我发出 Ajax 请求时,视图给出了 The view data.views.uploadFile didn't return an HttpResponse object. It returned None instead. 错误,因为它没有进入 if request.method == 'POST' 条件。当我从视图中删除该条件行时,它无法获取 img 文件。顺便说一句,这个uploadFile 视图工作正常,没有任何问题。奇怪的是,当我添加 upload_status 视图并重定向它时,它停止了工作。为了恢复,我删除了该部分并恢复了它,但它仍然不起作用。

我该如何解决这个问题?我错过了什么吗?

【问题讨论】:

    标签: python django ajax valueerror


    【解决方案1】:

    A.您应该使用the require_http_methods decorator将您的视图方法限制为您期望的实际方法

    from django.views.decorators.http import require_POST
    
    @require_POST
    def uploadFile(request):
        file = request.FILES.get('img')
        filename = file.name
        key = 'media/' + filename
        s3_resource = boto3.resource('s3')
        # ....
        return redirect('data:uploadStatus')
    

    这样,不使用 POST 对该端点的调用将收到 405 Method not allowed 响应。更容易调试和澄清问题所在。

    B.确保您在前端的 Ajax 调用遵循重定向。

    cache 参数对于 POST 不是必需的(除非您计划使用 IE8)

    关于 contentType=falseprocessData=false:在我看来,这仍然是一个常规的 multipart-formdata 调用。除非你知道你为什么这样做,否则不要这样做。您的 Django 代码看起来可以很好地处理常规表单数据,无需修改默认行为。

    C.您还必须实现错误回调:

    }).done(function(data) {
    }).fail(function(xhr, text, error) {
        console.log(text, error)
    });
    

    我想会发生什么你没有在 JS 代码中处理的错误。

    你还没有添加你的设置,所以我不能确定,但​​我想你没有正确设置 AJAX 的 CSRF 配置。解决此问题的一种方法是将 CSRF cookie 添加到 AJAX 请求中。 CSRF 表单字段和 cookie 都必须存在。

    https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax

    【讨论】:

    • 感谢您的回答。我已将 CSRF 添加到问题中的数据中。顺便说一句,我已经尝试过您提到的解决方案,但我收到了HTTP ERROR 405 错误。
    • 405 表示您的视图是使用您允许的方法(POST)以外的方法调用的。你需要调试它,除非你真的想允许其他方法。在这种情况下,您需要更改装饰器并正确处理该方法调用。
    猜你喜欢
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-21
    • 1970-01-01
    • 2021-08-10
    • 2015-09-15
    • 1970-01-01
    相关资源
    最近更新 更多