2012-12-09 102 views
8

我正在嘗試使用ajax提交登錄表單。我很困惑我應該如何處理例外/成功的迴應。我從服務器獲得200 OK,表單通過密碼/用戶名字段返回錯誤。根據服務器響應,我如何獲得顯示或重定向用戶到相應頁面的錯誤消息?Django Ajax登錄表格

JQUERY:

56 $(window).load(function(){                             
57 $('#login_form').submit(function(e){                           
58    e.preventDefault();                            
59  var request_url = document.getElementById('next').value                    
60   $.ajax({                               
61    type:"POST",                              
62    url: $(this).attr('action'),                          
63    data: $('#login_form').serialize(),                        
64    success: function(response){ $('#msg').text(response);                   
65    console.log(response);                           
66    },                                
67    error: function(xhr, ajaxOptions, thrownError){ alert($('#login_error').text('Username already taken. Please select another one.')}, 
68   });                                
69  });                                  
70 }); 

VIEW:更新

51 def login(request):                               
52  if request.method == 'POST':                            
53   request.session.set_test_cookie()                         
54   login_form = AuthenticationForm(request, request.POST)                    
55   if login_form.is_valid():                           
56    if request.is_ajax:                            
57     user = django_login(request, login_form.get_user())                   
58     if user is not None:                           
59      return HttpResponseRedirect(request.REQUEST.get('next', '/')) 
      **else:**                                
61    **return HttpResponseForbidden() # catch invalid ajax and all non ajax**           
60  else:                                 
61   login_form = AuthenticationForm(request)                        
62                                    
63  c = Context({                               
64   'next': request.REQUEST.get('next'),                         
65   'login_form': login_form,                           
66   'request':request,                             
67  })                                  
68  return render_to_response('login.html', c, context_instance=RequestContext(request))  

FORM:

7 <tt id="login_error"></tt>                                
8 <form id="login_form" action="" method="post">                        
9                                    
10  {{ login_form }}                               
11  <input type="submit" value="login"/>                          
12  <input type="hidden" id="request_path" name="next" value="/"/>                   
13 </form>                                 
14 <p>{{ request.get_full_path }}</p>                           
15 <tt id='msg'></tt>   

回答

8

儘管用json來做這件事確實是一個更好的做法,但假如你沒有真正從服務器傳回太多的信息,你可以不用。在Django端換取HttpResponseRedirectHttpResponse使用重定向網址作爲您的消息。如果ajax登錄失敗,請添加HttpResponseForbidden

def login(request):                               
    if request.method == 'POST':                            
     request.session.set_test_cookie()                         
     login_form = AuthenticationForm(request, request.POST)                    
     if login_form.is_valid():                           
      if request.is_ajax:                            
       user = django_login(request, login_form.get_user())                   
       if user is not None:                           
        return HttpResponse(request.REQUEST.get('next', '/')) 
     return HttpResponseForbidden() # catch invalid ajax and all non ajax               
    else:                                 
     login_form = AuthenticationForm()                                   
    c = Context({                               
     'next': request.REQUEST.get('next'),                         
     'login_form': login_form,                               
     'request':request,                             
    })                                  
    return render_to_response('login.html', c, context_instance=RequestContext(request)) 

然後在javascript方面,檢查響應的狀態碼。如果它是200,那麼這就是你的HttpResponse - 你想在響應消息中重定向到url。如果它是403,那麼這是你的HttpResponseForbidden - 登錄失敗。您可以通過標準的「登錄失敗」錯誤消息逃脫。

$.ajax({                               
    type:"POST",                              
    url: $(this).attr('action'),                          
    data: $('#login_form').serialize(), 
    // the success function is called in the case of an http 200 response                     
    success: function(response){ 
     // redirect to the required url 
     window.location = response;                          
    },                                
    error: function(xhr, ajaxOptions, thrownError){ 
     alert('login failed - please try again'); 
    }, 
}); 

恐怕我沒有測試過這個,但它應該給你一個想法。

欲瞭解更多信息請登錄docs for django's HttpResponse objects。然後檢查出jquery ajax docs

+1

值得注意的是你需要確保你正在處理正確的csrf令牌,否則你會遇到與Ajax形式的問題 - https://docs.djangoproject.com/en/1.4/ref/contrib/csrf/#ajax –

+0

謝謝艾丹!有效。現在我唯一需要弄清楚的是如何從響應中解析出「下一個」值,以便我可以正確地重定向頁面。 :) – user1462141

+0

它不應該需要解析,我期望它是一個字符串(我不知道沒有看到它是如何設置的)。我的猜測是POST或GET數據中沒有'next'屬性,所以默認值'/'正在被使用。你需要知道它是如何設置的。請查看此處的文檔以獲取有關請求的更多信息。請求字典 - https://docs.djangoproject.com/en/1.4/ref/request-response/#django.http.HttpRequest.REQUEST –

1
return HttpResponseRedirect(request.REQUEST.get('next', '/')) 

如果你正在做Ajax,你顯然不能使用它,客戶端必須負責重定向/顯示/無論在Ajax響應中發回的內容。如果登錄成功,發送一個JSON響應,告訴客戶端自己重定向(使用JavaScript重定向),如果不是,則發送帶有錯誤列表的JSON響應並使用javascript顯示它們。

+0

HttpResponseRedirect是一個狀態碼爲301的http響應。狀態碼非常容易被javascript XMLHttpRequest對象(或jQuery ajax函數)訪問。這可能不是最佳實踐(我不知道),但是說'顯然不能'使用http標頭將此信息傳遞給客戶端是無稽之談。 –

+0

好吧,我的壞,我已經做了一些進一步的閱讀,並且它看起來像300代碼不可訪問像其他http狀態代碼(因爲XMLHttpRequest返回前重定向,並提供與重定向相關的狀態代碼URL)。我仍然認爲說'你顯然不能'使用HttpResponseRedirect是不對的。 (@camus如果你想對你的答案做一個小改動,我會刪除我的反對票 - 除非答案改變,否則我不允許這樣做) –