从 AJAX 请求调用 django 视图(解析 celery task_id)

Posted

技术标签:

【中文标题】从 AJAX 请求调用 django 视图(解析 celery task_id)【英文标题】:Calling django view from AJAX request (parsing celery task_id) 【发布时间】:2019-01-08 23:35:15 【问题描述】:

我正在尝试将 celery 任务中的数据输出到单独的窗口中。我是javascriptAJAX 的新手,这就是我当前的问题所在。执行完一个view后,启动celery任务,渲染下一个html页面(success.html):

success.html

% block content %
  <body>
    % if task_id %
      <h1>task_id has been called:  task_id </h1>

    <script src="% static 'MyAPP/bootstrap/js/task_output_retrieval.js' %"></script>
    <script type='text/javascript'> task_state(" task_id "); </script>

    <script src="% static 'MyAPP/bootstrap/js/update-hello-user.js' %"></script>
    <script type='text/javascript'> second(); </script>

      <h1> END </h1>

    % endif %
  </body>
% endblock content %

我知道调用了JavaScript,因为至少打开了一个窗口。这是.js

task_output_retrieval.js

function task_state (task_id) 
    var taskID = task_id; 
    var newWin = window.open('', 'new window', 'width=200, height=100');

    $.ajax(
            url: '% url validate_task_state %', 
            data: 'taskID':taskID,
            method: 'POST',
            dataType : "json",
            success: function(data)
                $(newWin.document.body).html(data);
                newWin.document.write(data);
                newWin.document.close();
                newWin.focus();
                newWin.print();
                newWin.close();
            ,
            error: function () alert('An error occured'); 
    );


task_state(task_id);

还有url.py

url(r'^ajax/task_state/$', task_state, name='validate_task_state'), # for ajax

还有观点:

admin_scripts.py

def task_state(request):
    print ("You reached the task_state function")
    data = 'Fail' 
    task_id = request.GET.get('task_id') 
    #task_id = request.session['task_id']
    try:
        async_result = AsyncResult(task_id)
    except KeyError:
        ret = 'error':'No optimisation (or you may have disabled cookies).'
        return HttpResponse(json.dumps(ret))

    print ("request.is_ajax(): 0".format(request.is_ajax()))
    if request.is_ajax():
        if 'task_id' in request.POST.keys() and request.POST['task_id']:
            task_id = request.POST['task_id']
            async_result.get() 
            data = 
            'state': async_result.state,
            'result': async_result.result,
            
            #data = async_result.result or async_result.state
            print ("data: 0".format(data))
        else:
            data = 'No task_id in the request'
    else:
        raise SuspiciousOperation("This is not an ajax request.")

    json_data = json.dumps(data)
    return HttpResponse(json_data, content_type='application/json')

task_state 中仍有许多未解决的问题我不完全理解,通过反复试验我会到达那里,但现在,task_state 没有被调用。我怀疑的问题是 AJAX 调用(“url”),但我不知道为什么。我哪里错了?

更新:选中“JS Test Stuff”复选框后,success.html 会呈现,没有错误。 AJAX JavaScript (task_output_retrieval.js) 是从success.html 中调用的,这是经过验证的,因为我从success.html 调用了2 个JavaScript 文件(另一个是update-hello-user.js)。 task_output_retrieval.js 的窗口打开,update-hello-user.js 的弹出窗口也会显示。它在我调用视图的 task_output_retrieval.js 中:

    $.ajax(
                url: query_url,
)

但这不是渲染的。

这是控制台的输出:

[17/Aug/2018 04:59:12] INFO [django.server:124] "GET /MyApp/opt/ HTTP/1.1" 200 6631
async_result f2224e67-3e47-4980-9dc8-58622928e090
TASK_ID f2224e67-3e47-4980-9dc8-58622928e090
[17/Aug/2018 04:59:14] INFO [django.server:124] "POST /MyApp/opt/ HTTP/1.1" 200 6412
[17/Aug/2018 04:59:14] INFO [django.server:124] "GET /MyAppsite-static/MyApp/bootstrap/js/update-hello-user.js HTTP/1.1" 200 52
[17/Aug/2018 04:59:14] INFO [django.server:124] "GET /MyAppsite-static/MyApp/bootstrap/js/task_output_retrieval.js HTTP/1.1" 200 640

【问题讨论】:

【参考方案1】:

查看您的代码让我感到震惊的问题是您在 JavaScript 文件中使用了% url validate_task_state %。如果您按照最常见的推荐方法设置 Django 并提供其静态内容,则模板引擎不会处理您的 JavaScript 文件,并且 不会处理该模板标签。此外,它需要在其论点周围加上引号,所以% 'url validate_task_state' %

您应该更改您的 success.html 模板以将所需的 URL 传递给您的 task_state 函数,如下所示:

<script src="% static 'MyAPP/bootstrap/js/task_output_retrieval.js' %"></script>
<script type='text/javascript'> task_state("% url 'validate_task_state' %", " task_id "); </script>

并修改您的函数以采用新参数:

function task_state (query_url, task_id) 
    var taskID = task_id; 
    var newWin = window.open('', 'new window', 'width=200, height=100');

    $.ajax(
            url: query_url, 
            data: 'taskID':taskID,
            method: 'POST',
            dataType : "json",
            success: function(data)
                $(newWin.document.body).html(data);
                newWin.document.write(data);
                newWin.document.close();
                newWin.focus();
                newWin.print();
                newWin.close();
            ,
            error: function () alert('An error occured'); 
    );


您在评论中说 Django 没有看到该请求。一个常见的问题是 CSRF 保护:自定义 POST 请求需要传递 CSRF 令牌,否则将被拒绝。如何做到这一点的细节部分取决于您的具体配置,但一般来说,我会这样做:

// Grab the CSRF token from the cookie.
var csrftoken = $.cookie('csrftoken');
$.ajax(
  type: "POST",
  url: "... my url ...",
  headers: 
    // Pass the token with the query.
    'X-CSRFToken': csrftoken
  ,
  // other ajax options...
);

【讨论】:

感谢您的解释。更改我的代码引发了错误:Reverse for '' not found. '' is not a valid view function or pattern name. 它与url: query_url 有关,我也将其更改为url: 'query_url',,但似乎没有解决错误消息。我会继续调查。 % url ... % 的参数需要引号。所以% 'url validate_task_state' %,在参数周围加上引号。我刚刚编辑了我的答案来解决这个问题。我通过重新排列您的代码来写答案,起初并没有注意到缺少的引号。您绝对应该url: query_url 更改为url: 'query_url'url: query_url 是正确的。它将url 选项设置为函数的query_url 参数的值,该参数又设置为Django 模板中% url '...' % 的值。 您建议的更改有助于删除错误消息,并且至少会打开错误框和窗口,但是不会调用 view 函数 task_state,因为至少会执行 print 语句曾是。我怀疑url.py 中的网址,但到目前为止更改此网址无效。 我也在那里,并且想将此答案授予正确答案,只是缺少一小步(为什么我从 AJAX 调用中的观点没有被调用)。这是 .js 和 view.py 文件相互比较的问题,我在 url.py 中的映射,还是其他什么?我不再看到错误消息,但这一点代码并不能像我希望的那样工作。 有一大堆可能的问题会阻止您的请求得到答复。一个相对常见的罪魁祸首是 CSRF 保护,所以我已将其添加到我的答案中。如果这不是您的问题,那么可能会出现很多其他问题。您需要执行一些调试。在浏览器中打开开发人员工具,查看您的查询得到的响应。什么是状态码 404? 400? 502?还有什么?在开发模式下,Django 也会在控制台上报告信息。它是否报告了与您的失败查询相对应的内容?

以上是关于从 AJAX 请求调用 django 视图(解析 celery task_id)的主要内容,如果未能解决你的问题,请参考以下文章

在Django视图函数中无法检索AJAX请求数据值。

从 Ajax 调用 Django 视图

ajax请求返回django.urls.exceptions.NoReverseMatch后Django反向和重定向

Django 的 Ajax 视图

无法将 Ajax GET 调用中的数据值检索到 Django 视图中

Django通过ajax获取请求发出两个请求