Python Django 框架用POST提交时会出现这个问题
问题复现代码:
contact_form.html
def contact(request):
errors = []
if request.method == 'POST':
if not request.POST.get('subject',''):
errors.append("Enter a subject")
if not request.POST.get('message', ''):
errors.append("Enter a message")
if request.POST.get('email') and '@' not in request.POST['email']:
errors.append('Enter a valid e-mail address')
if not errors:
send_mail(request.POST['subject'],
request.POST['message'],
request.POST.get('email', '[email protected]'),
['[email protected]'],
)
return HttpResponse('/contact/thanks')
return render_to_response('contact_form.html',{'errors':errors})
修改方法:
def contact(request):
errors = []
if request.method == 'POST':
if not request.POST.get('subject',''):
errors.append("Enter a subject")
if not request.POST.get('message', ''):
errors.append("Enter a message")
if request.POST.get('email') and '@' not in request.POST['email']:
errors.append('Enter a valid e-mail address')
if not errors:
send_mail(request.POST['subject'],
request.POST['message'],
request.POST.get('email', '[email protected]'),
['[email protected]'],
)
return HttpResponse('/contact/thanks')
return render_to_response('contact_form.html',{'errors':errors},context_instance=RequestContext(request))
问题原因:
其实表单中的{% csrf_token %}在html页面被加载的时候就已经被赋值了,而post的时候需要将这个被赋值的csrf_token发送给服务端进行验证,如果验证成功才能进行post操作,否则就被认为是csrf攻击。
而上文中的contact_form.html中一开始并没有由服务器给出一个csrf_token,在post的时候自然而然就不能成功验证。
而 context_instance=RequestContext(rq)的作用就是给这个csrf_token进行赋值,上文中却把赋值的操作在post之后进行,而正确地操作是在post之前打开html页面的时候就赋值