现象
表单界面如下:
在点击提交之后,出现如下错误页面:
HTML的代码如下:
contact_form.html
<!DOCTYPE HTML PUBLIC ><html>
<head><title>Contact us</title>
</head><body><h1>Contact us</h1>{% if errors %}<ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}<form action="/contact/" method="post"><p>Subject: <input type="text" name="subject" value="{{ subject }}"></p><p>Your e-mail (optional): <input type="text" name="email" value="{{ email }}"></p><p>Message: <textarea name="message" rows="10" cols="50">{{ message }}</textarea></p><input type="submit" value="Submit"></form>
</body>
</html>
view代码如下:
view.py
# -*- coding: utf-8 -*-from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_responsedef 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', 'noreply@example.com'),['siteowner@example.com'],)return HttpResponseRedirect('/contact/thanks/')return render_to_response('contact_form.html', {'errors': errors,'subject': request.POST.get('subject', ''),'message': request.POST.get('message', ''),'email': request.POST.get('email', ''),})
一般浏览器都是开启了cookies的,所以在上面图中的错误信息中,我们主要关注后三点,根据提示进行更改:
解决方案一:CSRF验证设置
1. 在 view.py 中的 render_to_response 中,使用 RequestContext 来代替默认的 Context 。
view.py
# -*- coding: utf-8 -*-from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContextdef 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', 'noreply@example.com'),['siteowner@example.com'],)return HttpResponseRedirect('/contact/thanks/')return render_to_response('contact_form.html', {'errors': errors,'subject': request.POST.get('subject', ''),'message': request.POST.get('message', ''),'email': request.POST.get('email', ''),},context_instance=RequestContext(request))
2. 在模板文件中的 form 表单内添加 {% csrf_token %} 。
contact_form.html
<!DOCTYPE HTML PUBLIC ><html>
<head><title>Contact us</title>
</head><body><h1>Contact us</h1>{% if errors %}<ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}<form action="/contact/" method="post"><br />{% csrf_token %}<br /><p>Subject: <input type="text" name="subject" value="{{ subject }}"></p><p>Your e-mail (optional): <input type="text" name="email" value="{{ email }}"></p><p>Message: <textarea name="message" rows="10" cols="50">{{ message }}</textarea></p><input type="submit" value="Submit"></form>
</body>
</html>
测试运行,成功!
PS:上文中图片中的错误信息第四条,在建立django工程的时候 setting.py 已经自动添加了 'django.middleware.csrf.CsrfViewMiddleware',
MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.auth.middleware.SessionAuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware','django.middleware.security.SecurityMiddleware','django.middleware.locale.LocaleMiddleware',
)
解决方案二:不使用 CSRF 验证
1. 在 setting.py 文件中删除 'django.middleware.csrf.CsrfViewMiddleware', ,如下所示
MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware',#'django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.auth.middleware.SessionAuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware','django.middleware.security.SecurityMiddleware','django.middleware.locale.LocaleMiddleware',
)
2. 移除 form 表单中的 {% csrf_token %} 标记。如下所示:
contact_form.html
<!DOCTYPE HTML PUBLIC ><html>
<head><title>Contact us</title>
</head><body><h1>Contact us</h1>{% if errors %}<ul>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}<form action="/contact/" method="post"><p>Subject: <input type="text" name="subject" value="{{ subject }}"></p><p>Your e-mail (optional): <input type="text" name="email" value="{{ email }}"></p><p>Message: <textarea name="message" rows="10" cols="50">{{ message }}</textarea></p><input type="submit" value="Submit"></form>
</body>
</html>
3. 在 view.py 中的 render_to_response 中,不使用 RequestContext 。如下所示:
view.py
# -*- coding: utf-8 -*-from django.core.mail import send_mail
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContextdef 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', 'noreply@example.com'),['siteowner@example.com'],)return HttpResponseRedirect('/contact/thanks/')return render_to_response('contact_form.html', {'errors': errors,'subject': request.POST.get('subject', ''),'message': request.POST.get('message', ''),'email': request.POST.get('email', ''),})
重新运行,测试成功!