2011-10-19 45 views
2

私は、「投票する」ボタンのように、ユーザークリックで増加する整数フィールドを持つモデルを持っています。django ajaxのエラー405

ボタンは詳細ビューにのみ表示されます。投票数を増やすには、ajax POSTを送信します。問題は、ビューを実行する前でもdjangoが405(メソッドは許されない)エラーを返すことです。これを引き起こす原因は何ですか?ここで

は私のコードです:

views.py(実行されません)

@require_POST 
def vote_proposal(request, space_name): 

    """ 
    Increment support votes for the proposal in 1. 
    """ 
    prop = get_object_or_404(Proposal, pk=request.POST['propid']) 
    proposal_form = VoteProposal(request.POST or None, instance=prop) 

    if request.method == "POST" and request.is_ajax: 
     if proposal_form.is_valid(): 
      vote = proposal_form.cleaned_data['propid'] 
      vote.support_votes += 1 
      vote.save() 
      msg = "The vote has been saved." 
     else: 
      msg = "The vote didn't pass validation." 
    else: 
     msg = "An error has ocurred." 

    return HttpResponse(msg) 

のjQueryコード:

<script type="text/javascript"> 
    function upvote(proposal) { 
     var request = $.ajax({ 
      type: "POST", 
      url: "../add_support_vote/", 
      data: { propid: proposal } 
     }); 

     request.done(function(msg) { 
      var cur_votes = $("#votes span").html(); 
      var votes = cur_votes += 1; 
      $("#votes span").html().fadeOut(1000, function(){ 
       $("#votes span").html(votes).fadeIn(); 
      }); 
     }); 

     request.fail(function(jqXHR, textStatus) { 
      $("#jsnotify").notify("create", { 
       title:"Couldn't vote the proposal", 
       text:"There has been an error." + textStatus, 
       icon:"alert.png" 
      }); 
     }) 
    } 
</script> 

urls.py

urlpatterns = patterns('e_cidadania.apps.proposals.views', 

    url(r'^$', ListProposals.as_view(), name='list-proposals'), 

    url(r'^add/$', 'add_proposal', name='add-proposal'), 

    url(r'^(?P<prop_id>\w+)/edit/$', 'edit_proposal', name='edit-proposal'), 

    url(r'^(?P<prop_id>\w+)/delete/$', DeleteProposal.as_view(), name='delete-proposal'), 

    url(r'^(?P<prop_id>\w+)/', ViewProposal.as_view(), name='view-proposal'), 

    url(r'^add_support_vote/', 'vote_proposal'), 

) 

テンプレート

<div id="votes"> 
    <span style="font-size:30px;text-align:center;"> 
     {{ proposal.support_votes }} 
    </span><br/> 
    <button onclick="upvote({{ proposal.id }})" class="btn small">{% trans "support" %}</button> 
</div> 
+0

これを忘れた可能性があります:https://docs.djangoproject。com/en/dev/ref/contrib/csrf /#ajax – Ahsan

+0

私はそれを含んでおり、POSTイベントはプラットフォーム内の他の関数でうまくいきますので、ちょっと混乱しています –

+2

相対URL 'url:" ../ add_support_vote/"、' '$ .ajax'には? POSTを許可しない別のビューは、Ajax呼び出しをトリガするページの場所に応じて 'vote_proposal()'の代わりに呼び出されるかもしれないと想像することができます。 –

答えて

4

問題が$.ajaxに相対URL url: "../add_support_vote/"が原因で発生することができませんでした。また、AJAX呼び出しからURLを扱うビュー機能を取得するためにresolveを使用するために、最終的な小さな提案が


? Ajax呼び出しをトリガーするページの場所によっては、POSTを許可しない別のビューがvote_proposal()の代わりに呼び出される可能性があります。

1

残念ながら、この小さな調査では問題は見つかりませんでしたが、コードを修正して動作させる方法を明確にすることができれば幸いです。私はボタンの最初の1、AJAX呼び出しハンドラボタンtest.htmlテスト目的のために簡略化ビットと

from django.conf import settings 
from django.conf.urls.defaults import patterns, include, url  
from django.views.generic.simple import direct_to_template 

urlpatterns = patterns(''  
    url(r'^$', direct_to_template , {'template':'test.html'}), 
    url(r'^test/', include('testapp.urls')), 
)  

if settings.DEBUG: 
    urlpatterns += patterns(
     '', 
     url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), 
) 

マイテンプレートのtestapに2番目の2つのビューが作成したメインurls.py

。またcsrf hook403 CSRF verificationエラーを防止するために追加されました:testappとから

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<script src="{{ MEDIA_URL }}js/jquery-1.6.1.min.js" type="text/javascript"></script> 
<script type="text/javascript"> 
    $(document).ajaxSend(function(event, xhr, settings) { 
     function getCookie(name) { 
      var cookieValue = null; 
      if (document.cookie && document.cookie != '') { 
       var cookies = document.cookie.split(';'); 
       for (var i = 0; i < cookies.length; i++) { 
        var cookie = jQuery.trim(cookies[i]); 
        // Does this cookie string begin with the name we want? 
        if (cookie.substring(0, name.length + 1) == (name + '=')) { 
         cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 
         break; 
        } 
       } 
      } 
      return cookieValue; 
     } 
     function sameOrigin(url) { 
      // url could be relative or scheme relative or absolute 
      var host = document.location.host; // host + port 
      var protocol = document.location.protocol; 
      var sr_origin = '//' + host; 
      var origin = protocol + sr_origin; 
      // Allow absolute or scheme relative URLs to same origin 
      return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || 
       (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || 
       // or any other URL that isn't scheme relative or absolute i.e relative. 
       !(/^(\/\/|http:|https:).*/.test(url)); 
     } 
     function safeMethod(method) { 
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
     } 

     if (!safeMethod(settings.type) && sameOrigin(settings.url)) { 
      xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 
     } 
    }); 

     function upvote(proposal) { 
      var request = $.ajax({ 
       type: "POST", 
       url: "../test/add_support_vote/", 
       data: { propid: proposal } 
      }); 

      request.done(function(msg) { 
       var cur_votes = $("#votes span").html(); 
       var votes = cur_votes += 1; 
       $("#votes span").html().fadeOut(1000, function(){ 
        $("#votes span").html(votes).fadeIn(); 
       }); 
      }); 

      request.fail(function(jqXHR, textStatus) { 
       $("#jsnotify").notify("create", { 
        title:"Couldn't vote the proposal", 
        text:"There has been an error." + textStatus, 
        icon:"alert.png" 
       }); 
      }) 
     } 
    </script> 
</head> 
<body> 
<div id="votes"> 
    <button onclick="upvote(1)" class="btn small">support</button> 
</div> 
</body> 
</html> 

urls.py

最大限に発行し

from django.http import HttpResponse 
from django.shortcuts import get_object_or_404 
from django.views.decorators.http import require_POST 

@require_POST 
def vote_proposal(request): 
    return HttpResponse('ok') 

をローカライズするために簡素化され、それが作品だ

from django.conf.urls.defaults import * 
from .views import vote_proposal 

urlpatterns = patterns('', 
    url(r'^add_support_vote/', vote_proposal), 

) 

views.pyのように見えます。 200 HTTPレスポンスがあります。

from django.core.urlresolvers import resolve 
resolve('/test/add_support_vote/') 
# returns ResolverMatch(func=<function vote_proposal at 0x2b17230>, args=(), kwargs={}, url_name='testapp.views.vote_proposal', app_name='None', namespace='') 
+0

"解決"とその答えに+1。私はその機能について知らなかった。残念ながら、この問題はURLであり、何らかの理由で「ビュープロポーザル」のビューがadd_support_voteを乱していました。ちょうどそれが働いた順序を変更する:) –

+0

おかげで、あなたを助けてうれしい –

0

405エラー私はPOSTメソッドを持たないTemplateViewにPOSTしようとしていたため、誰でも役に立ちました。

代わりにFormView(POSTメソッドがあります)に変更しました。

関連する問題