【问题标题】:Http302 Response when using Ajax to post to Django view使用 Ajax 发布到 Django 视图时的 Http302 响应
【发布时间】:2015-08-22 01:00:42
【问题描述】:

我正在尝试构建一个使用 ajax 接受输入的网络应用程序。输入在服务器端发送到 Django,我很难让 url 正确重定向。我知道目前的问题与 django 翻译应用程序有关。

这是相关部分。

Ajax

 $(document).ready(function(){
  $('#applicant_form').on('submit', function(event){
    event.preventDefault() //this will stop the file from submitting the form manually.
    $.ajax({
        url :'/save_applicant/', // the endpoint
        type : "POST", // http method
        data : { the_post : "Yay" }, // data sent with the post request
        dataType: "json",
        // handle a successful response
        success : function(json) {
            console.log("success"); // another sanity check
        },

        // handle a non-successful response
        error : function(xhr,errmsg,err) {
            $('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
                " <a href='#' class='close'>&times;</a></div>"); // add the error to the dom
            console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        }
    });
  });
});

HTML/DJANGO 模板

<form method = "POST" action = "" class="form bgform" id="applicant_form">
    {% csrf_token %}
    {{ applicant_form|crispy }}
    <input class="btn btn-default" type="submit" name="Save" />
</form>

views.py

def save_applicant(request):
if request.method =='POST':
    id = None
    if 'applicant' in request.session:
        id = request.session['applicant']

    applicant_form = ApplicantForm(request.POST)
    if applicant_form.is_valid():
        session_applicant  = applicant_form.save(commit=False)
        if id:
            session_applicant.id = id
        else:
            session_applicant.save()
            request.session['applicant'] = session_applicant.id 
        return HttpResponse(json.dumps({'status':'applicant_saved'}), content_type='application/json')

    else:
        return HttpResponse(applicant_form.errors.as_json(),content_type='application/json')

else:
    return HttpResponse(json.dumps({'status':'not_post'}),content_type='application/json')

urls.py

from django.conf.urls import include, url
from django.contrib import admin
from django.conf.urls.i18n import i18n_patterns

urlpatterns = [
]
urlpatterns += i18n_patterns(
    url(r'^$', 'plan_b_profile.views.home', name='home'),
    url(r'^save_applicant/','plan_b_profile.views.save_applicant',name='save_applicant'),
    url(r'^admin/', include(admin.site.urls)),
)

命令行

[21/Aug/2015 20:53:43]"POST /save_applicant HTTP/1.1" 302 0
[21/Aug/2015 20:53:43]"GET /en/save_applicant/ HTTP/1.1" 200 22 <---- HOW TO FIX THIS

再次感谢!

【问题讨论】:

  • 这是整个视图吗?
  • 你想做什么?
  • 嘿,我添加了完整视图,抱歉,我不确定它是否相关。我只是想使用 ajax POST 到 /save_applicant/。虽然我有翻​​译,而不是像往常一样发布到 url,它更改为 GET 调用并添加 /en/save_applicant/ 。不知道如何解决这个问题,所以这个重定向不会发生。
  • 它正在执行GET,因为您正在提交表单而不是使用$.preventDefault()。我假设页面在点击提交后重新加载?
  • 我添加了事件默认值(见上文),当我点击提交按钮时页面不会重新加载,而是转到我的视图。视图发现它不是 POST,因为它现在是 GET,然后我在控制台上看到:'status':'not post'

标签: jquery python ajax django


【解决方案1】:

我认为这个问题的最佳解决方案是在 JavaScript 中动态分配帖子 url。

重写你的模板,这样你就可以将你的 URL 存储在 django 反转的地方,例如action 的形式:

<form method = "POST" action="{% url "save_applicant" %}" class="form bgform" id="applicant_form">
    {% csrf_token %}
    {{ applicant_form|crispy }}
    <input class="btn btn-default" type="submit" name="Save" />
</form>

并将 AJAX 发布到该 URL 而不是静态 URL,它已经带有语言前缀,因此不会发生重定向:

$(document).ready(function(){
  $('#applicant_form').on('submit', function(event){
    event.preventDefault() //this will stop the file from submitting the form manually.
    $.ajax({
        url :$(this).attr('action'), // the endpoint
        type : "POST", // http method
        data : { the_post : "Yay" }, // data sent with the post request
        dataType: "json",
        // handle a successful response
        success : function(json) {
            console.log("success"); // another sanity check
        },

        // handle a non-successful response
        error : function(xhr,errmsg,err) {
            $('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
                " <a href='#' class='close'>&times;</a></div>"); // add the error to the dom
            console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
        }
    });
  });
});

【讨论】:

  • 另外:在模板或 Javascript 中硬编码 URL 不是好的解决方案
  • 非常感谢!! :) 并感谢您向我展示如何获取 url 而无需对其进行硬编码。
【解决方案2】:

所以我离开了这个问题,并意识到我的愚蠢错误。我刚刚将 urls.py 更改为以下内容:

from django.conf.urls import include, url
from django.contrib import admin
from django.conf.urls.i18n import i18n_patterns

urlpatterns = [
    url(r'^save_applicant/','plan_b_profile.views.save_applicant',name='save_applicant'),
]
urlpatterns += i18n_patterns(
    url(r'^$', 'plan_b_profile.views.home', name='home'),
    url(r'^admin/', include(admin.site.urls)),
)

【讨论】:

    【解决方案3】:

    即使使用您自己的解决方案,如果您在使用 i18n 语言扩展程序时从您的视图返回 404 Not Found 状态,您仍然可能会发现收到 302 重定向。当某些请求参数不正确时,我会这样做(我对 HTTP GET 和 HTTP/AJAX POST 使用相同的视图)。

    原因是一些 Django 中间件(我认为是 LocaleMiddleware)会在中间件堆栈向上的过程中处理响应,看到页面没有找到,并返回一个 302 重定向,而不是在浏览器的语言前缀之前。然后,当下一个请求(在这种情况下)又找不到此请求时,您将获得不同的 404 Not Found 响应。这很糟糕,因为您永远无法看到原始请求失败的原因。

    在您的情况下,您可以通过以下方式解决此问题:

    ...
    urlpatterns = [
        url(r'^en/save_applicant/','plan_b_profile.views.save_applicant',name='save_applicant'),
    ]
    ...
    

    这会使有问题的中间件误以为它已经是一个特定于语言的页面(实际上是因为您在按钮和 ajax 中返回英文)。

    您还可以使用solid-i18n-url 之类的解决方案完全删除重定向。

    编辑:但是经过反思,首先返回这样的 404 可能是个坏主意;一个 400 Bad Request 会更好..

    【讨论】:

      【解决方案4】:

      不管怎样,我在 Django 的 HTTP 302 响应中遇到了同样的问题。如果 URL 中没有斜杠,Django 将返回 HTTP 302 我确实在您的模板代码中看到了斜杠,但 Django 日志讲述了一个不同的故事):

      [21/Aug/2015 20:53:43]"POST **/save_applicant** HTTP/1.1" 302 0
      

      确保 URL 末尾的尾部斜杠(即 /save_applicant**/**)应该可以正常工作。

      @GwynBleidD 的回答,推荐使用内置的 {% url %} 模板。

      【讨论】:

        猜你喜欢
        • 2020-05-21
        • 2011-12-06
        • 2013-08-24
        • 2015-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-25
        • 2016-09-03
        相关资源
        最近更新 更多