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

pym*_*mat 7 javascript django ajax django-urls celery

我正在尝试将芹菜任务中的数据输出到一个单独的窗口中.我是一个新手JavaScriptAJAX,而这正是我目前的问题所在.执行视图后,将启动celery任务并success.html呈现下一个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 %}
Run Code Online (Sandbox Code Playgroud)

我知道这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);
Run Code Online (Sandbox Code Playgroud)

url.py:

url(r'^ajax/task_state/$', task_state, name='validate_task_state'), # for ajax
Run Code Online (Sandbox Code Playgroud)

并且观点:

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')
Run Code Online (Sandbox Code Playgroud)

还有很多未解决的问题task_state我不完全理解,通过反复试验,我会到达那里,但是现在,task_state它还没有被调用.我怀疑的问题是AJAX调用("url"),但我无法弄清楚原因.我哪里错了?

更新:在选中"JS Test Stuff"复选框后,success.html渲染,无错误.task_output_retrieval.js从内部调用AJAX JavaScript()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,
)
Run Code Online (Sandbox Code Playgroud)

但这不会呈现.

这是控制台的输出:

[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
Run Code Online (Sandbox Code Playgroud)

Lou*_*uis 2

在查看您的代码时,我发现的问题是您{% url validate_task_state %}在 JavaScript 文件中的使用。如果您遵循最常见的推荐方法来设置 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>
Run Code Online (Sandbox Code Playgroud)

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

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'); }
    });
}
Run Code Online (Sandbox Code Playgroud)

您在评论中说过 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...
});
Run Code Online (Sandbox Code Playgroud)