Django:通过 ajax 将 csrf 令牌传递给 UpdateView 405 方法未找到错误
Django: Passing a csrf token through ajax to an UpdateView 405 method not found error
我正在创建一个常见问题解答应用程序。在我的文章详细信息页面中,我正在尝试实施投票系统。目标是让用户在发现有用的文章时对其进行投票。我不希望在用户单击投票按钮时刷新页面。我选择使用模板中的 Ajax 调用以及 url 到 UpdateView。
Django 需要传递一个 csrf 令牌。我遇到的问题是 405 (Method Not Allowed)
错误。我已经在 chrome dev 的网络设置中验证了 csrf 令牌正在生成并在 http header 中分配。我认为问题可能出在观点上,但到目前为止我所尝试的一切都没有成功。任何方向都会有所帮助。
编辑更新:
我正在使用 Django 1.10
Url:
from django.conf.urls import url
from faq.views import *
urlpatterns = [
url(r'^ironfaq/$', DashboardView.as_view()),
url(r'^ironfaq/(?P<slug>[\w-]+)/$', SectionView.as_view()),
url(r'^ironfaq/(?P<topic_slug>[\w-]+)/(?P<section_slug>[\w-]+)/(?P<pk>\d+)/$',
ArticleDetailView.as_view(), name="faq-article-detail"),
url(r'^ironfaq/topic/create/$', TopicCreateView.as_view()),
url(r'^ironfaq/section/create/$', SectionCreateView.as_view()),
url(r'^ironfaq/(?P<topic_pk>\d+)/article/create/$', ArticleCreateView.as_view()),
url(r'^ironfaq/topic/update/(?P<pk>\d+)/$', TopicUpdateView.as_view()),
url(r'^ironfaq/section/update/(?P<pk>\d+)/$', SectionUpdateView.as_view()),
url(r'^ironfaq/article/update/(?P<pk>\d+)/$', ArticleUpdateView.as_view()),
url(r'^ironfaq/topic/delete/(?P<pk>\d+)/$', TopicDeleteView.as_view()),
url(r'^ironfaq/section/delete/(?P<pk>\d+)/$', SectionDeleteView.as_view()),
url(r'^ironfaq/article/delete/(?P<pk>\d+)/$', ArticleDeleteView.as_view()),
url(r'^ironfaq/article/vote/(?P<pk>\d+)$/', ArticleVoteView.as_view()),
]
模板脚本:
{% block scripts %}
<script>
$(document).ready(function(){
var csrftoken = Cookies.get('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function post_call(vote_data){
var data = {vote_type: vote_data};
var id = {{ object.id }};
$.ajax({
url: "/ironfaq/article/vote/"+id+"/",
type: "POST",
data: data,
}).done(function() {
console.log("POST!");
});
}
var vote_up = "vote_up";
var vote_down = "vote_down";
var thumbs_up = $('#thumbs_up');
var thumbs_down = $('#thumbs_down');
thumbs_up.on('click', function(){
post_call(vote_up)
});
thumbs_down.on('click', function(){
post_call(vote_down)
});
});
</script>
{% endblock %}
视图:
class ArticleVoteView(UpdateView):
model = Article
fields = []
def form_valid(self, form):
article = form.save(commit=False)
vote_type = self.request.POST.get('vote_type')
if vote_type == 'vote_up':
article.vote_up = article.vote_up + 1
article.save()
elif vote_down == 'vote_down':
article.vote_down = article.vote_down + 1
article.save()
data = {'status': 'success', 'vote_type': vote_type, 'yes_count': article.vote_up,
'total_votes': article.total_votes()}
return HttpResponse(json.dumps(data))
您对 /ironfaq/article/vote/<id>
的 post 请求似乎与此 url 模式匹配:
url(r'^ironfaq/(?P<topic_slug>[\w-]+)/(?P<section_slug>[\w-]+)/(?P<pk>\d+)/$',
ArticleDetailView.as_view(), name="faq-article-detail"),
由于详细视图仅处理获取请求,因此您的 post 请求会导致 405 响应。
您要么需要重新设计 url 模式以免它们发生冲突,要么将 faq-article-detail
url 模式移到投票 url 模式下方(并且任何其他与之冲突的)。
我正在创建一个常见问题解答应用程序。在我的文章详细信息页面中,我正在尝试实施投票系统。目标是让用户在发现有用的文章时对其进行投票。我不希望在用户单击投票按钮时刷新页面。我选择使用模板中的 Ajax 调用以及 url 到 UpdateView。
Django 需要传递一个 csrf 令牌。我遇到的问题是 405 (Method Not Allowed)
错误。我已经在 chrome dev 的网络设置中验证了 csrf 令牌正在生成并在 http header 中分配。我认为问题可能出在观点上,但到目前为止我所尝试的一切都没有成功。任何方向都会有所帮助。
编辑更新:
我正在使用 Django 1.10
Url:
from django.conf.urls import url
from faq.views import *
urlpatterns = [
url(r'^ironfaq/$', DashboardView.as_view()),
url(r'^ironfaq/(?P<slug>[\w-]+)/$', SectionView.as_view()),
url(r'^ironfaq/(?P<topic_slug>[\w-]+)/(?P<section_slug>[\w-]+)/(?P<pk>\d+)/$',
ArticleDetailView.as_view(), name="faq-article-detail"),
url(r'^ironfaq/topic/create/$', TopicCreateView.as_view()),
url(r'^ironfaq/section/create/$', SectionCreateView.as_view()),
url(r'^ironfaq/(?P<topic_pk>\d+)/article/create/$', ArticleCreateView.as_view()),
url(r'^ironfaq/topic/update/(?P<pk>\d+)/$', TopicUpdateView.as_view()),
url(r'^ironfaq/section/update/(?P<pk>\d+)/$', SectionUpdateView.as_view()),
url(r'^ironfaq/article/update/(?P<pk>\d+)/$', ArticleUpdateView.as_view()),
url(r'^ironfaq/topic/delete/(?P<pk>\d+)/$', TopicDeleteView.as_view()),
url(r'^ironfaq/section/delete/(?P<pk>\d+)/$', SectionDeleteView.as_view()),
url(r'^ironfaq/article/delete/(?P<pk>\d+)/$', ArticleDeleteView.as_view()),
url(r'^ironfaq/article/vote/(?P<pk>\d+)$/', ArticleVoteView.as_view()),
]
模板脚本:
{% block scripts %}
<script>
$(document).ready(function(){
var csrftoken = Cookies.get('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
function post_call(vote_data){
var data = {vote_type: vote_data};
var id = {{ object.id }};
$.ajax({
url: "/ironfaq/article/vote/"+id+"/",
type: "POST",
data: data,
}).done(function() {
console.log("POST!");
});
}
var vote_up = "vote_up";
var vote_down = "vote_down";
var thumbs_up = $('#thumbs_up');
var thumbs_down = $('#thumbs_down');
thumbs_up.on('click', function(){
post_call(vote_up)
});
thumbs_down.on('click', function(){
post_call(vote_down)
});
});
</script>
{% endblock %}
视图:
class ArticleVoteView(UpdateView):
model = Article
fields = []
def form_valid(self, form):
article = form.save(commit=False)
vote_type = self.request.POST.get('vote_type')
if vote_type == 'vote_up':
article.vote_up = article.vote_up + 1
article.save()
elif vote_down == 'vote_down':
article.vote_down = article.vote_down + 1
article.save()
data = {'status': 'success', 'vote_type': vote_type, 'yes_count': article.vote_up,
'total_votes': article.total_votes()}
return HttpResponse(json.dumps(data))
您对 /ironfaq/article/vote/<id>
的 post 请求似乎与此 url 模式匹配:
url(r'^ironfaq/(?P<topic_slug>[\w-]+)/(?P<section_slug>[\w-]+)/(?P<pk>\d+)/$',
ArticleDetailView.as_view(), name="faq-article-detail"),
由于详细视图仅处理获取请求,因此您的 post 请求会导致 405 响应。
您要么需要重新设计 url 模式以免它们发生冲突,要么将 faq-article-detail
url 模式移到投票 url 模式下方(并且任何其他与之冲突的)。