在上篇表单验证中,过程中可谓坎坷,记录一下错误问题及解决方案。
我们用到的模板contact_form.html如下,其他urls.py自行去修改。
<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"></p> <p>Your e-mail (optional): <input type="text" name="email"></p> <p>Message: <textarea name="message" rows="10" cols="50"></textarea></p> <input type="submit" value="Submit"> </form> </body> </html>
视图函数
1 from django.core.mail import send_mail 2 from django.http import HttpResponseRedirect 3 4 def contact(request): 5 errors = [] 6 if request.method == 'POST': 7 if not request.POST.get('subject', ''): 8 errors.append('Enter a subject.') 9 if not request.POST.get('message', ''): 10 errors.append('Enter a message.') 11 if request.POST.get('email') and '@' not in request.POST['email']: 12 errors.append('Enter a valid e-mail address.') 13 if not errors: 14 try: 15 send_mail( 16 request.POST['subject'], 17 request.POST['message'], 18 request.POST.get('email', 'noreply@example.com'), 19 ['siteowner@example.com'], 20 ) 21 except: 22 return HttpResponse("exception.") 23 24 return HttpResponseRedirect('/contact/thanks/') 25 return render_to_response('contact_form.html', 26 {'errors': errors})
由于这示例是个发送邮件,而本地不一定配置了相关环境,我们使用简单地Console backend进行输出邮件内容。
只需要在settings.py中增加如下一句即可:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
我们的视图方法很简单,发送邮件成功(dos窗口会输出邮件相关信息),并转向到thanks视图;失败则会停留在本页并提示错误。
方法看似没问题,可是执行看一下结果(下图是输入正确或错误一样的结果截图,也就是response时候的错误)
针对该问题进行查找解决方案,并一点点修改。
首先引入RequestContext
from django.template import Context,RequestContext
修改模板中加入
1 <form action="/contact/" method="post"> 2 {% csrf_token %} 3 <p>Subject: <input type="text" name="subject"></p> 4 <p>Your e-mail (optional): <input type="text" name="email"></p> 5 <p>Message: <textarea name="message" rows="10" cols="50"></textarea></p> 6 <input type="submit" value="Submit"> 7 </form>
settings.py中添加的那个CsrfViewMiddleware,在原来的配置中就是包含的,不用管。再进行查看结果,还是一样的!这里就不贴图了。
想想我们唯一的改动就是增加了一个模块类RequestContext,但是他有什么用呢?我们并没有改动代码,是不是它对代码会有什么影响?
官网上有这样一段示例
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
和我们的视图函数中是不一样的!
参照这个示例,我们开始修改视图:
1 def contact(request): 2 errors = [] 3 if request.method == 'POST': 4 if not request.POST.get('subject', ''): 5 errors.append('Enter a subject.') 6 if not request.POST.get('message', ''): 7 errors.append('Enter a message.') 8 if request.POST.get('email') and '@' not in request.POST['email']: 9 errors.append('Enter a valid e-mail address.') 10 if not errors: 11 try: 12 send_mail( 13 request.POST['subject'], 14 request.POST['message'], 15 request.POST.get('email', 'noreply@example.com'), 16 ['siteowner@example.com'], 17 ) 18 except: 19 return HttpResponse("exception.") 20 21 return HttpResponseRedirect('/contact/thanks/') 22 return render_to_response('contact_form.html', 23 {'errors': errors},context_instance=RequestContext(request))
我们增加了这一句,然后看效果吧
okay,我们成功了!
当我们输入正确的邮箱时,正确跳转到thanks视图,效果如下:
顺便一提,在我们的dos窗口看到了邮件信息,说明settings.py中的那一句还是好用的:
最终的视图函数如下
1 from django.template import Context,RequestContext 2 from django.core.mail import send_mail 3 from django.http import HttpResponseRedirect 4 5 def contact(request): 6 errors = [] 7 if request.method == 'POST': 8 if not request.POST.get('subject', ''): 9 errors.append('Enter a subject.') 10 if not request.POST.get('message', ''): 11 errors.append('Enter a message.') 12 if request.POST.get('email') and '@' not in request.POST['email']: 13 errors.append('Enter a valid e-mail address.') 14 if not errors: 15 try: 16 send_mail( 17 request.POST['subject'], 18 request.POST['message'], 19 request.POST.get('email', 'noreply@example.com'), 20 ['siteowner@example.com'], 21 ) 22 except: 23 return HttpResponse("exception.") 24 25 return HttpResponseRedirect('/contact/thanks/') 26 return render_to_response('contact_form.html', 27 {'errors': errors},context_instance=RequestContext(request)) 28 29 def thanks(request): 30 return HttpResponse("thanks for your suggestion!")
模板如下
1 <html> 2 <head> 3 <title>Contact us</title> 4 </head> 5 <body> 6 <h1>Contact us</h1> 7 8 {% if errors %} 9 <ul> 10 {% for error in errors %} 11 <li>{{ error }}</li> 12 {% endfor %} 13 </ul> 14 {% endif %} 15 16 <form action="/contact/" method="post"> 17 {% csrf_token %} 18 <p>Subject: <input type="text" name="subject"></p> 19 <p>Your e-mail (optional): <input type="text" name="email"></p> 20 <p>Message: <textarea name="message" rows="10" cols="50"></textarea></p> 21 <input type="submit" value="Submit"> 22 </form> 23 </body> 24 </html>
注意:
return HttpResponseRedirect('/contact/thanks/')
这只是一个普通的HttpResponse,不可修改如下
return HttpResponseRedirect('/contact/thanks/',context_instance=RequestContext(request))
报错如下
小结
有问题是好事,解决问题的过程,能学到更多东西,继续加油!