Django 渲染未验证数据的表单
我写了这个联系表单,参考了一些Django的文档:
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['name@e-mail.com']
if cc_myself:
recipients.append(sender)
m = '%s\n\n-----------------\n%s' % (message, name)
from django.core.mail import send_mail
send_mail(subject, m, sender, recipients)
return HttpResponseRedirect('/kontakt/tack/')
else:
form = ContactForm()
return render(request, 'contact/index.html', {
'form': form,
})
问题是,如果表单没有通过验证,它会返回一个空的表单。这对那些写了很长信息但忘记填写名字的人来说,可能会很烦人。
我通过把下面的代码中最后的 else:
改成这样来解决这个问题:
try:
form = ContactForm(form.cleaned_data)
except UnboundLocalError:
form = ContactForm()
我需要在页面第一次渲染时使用 try
语句,因为那时候还没有 form.cleaned_data
。这样做是有效的,但看起来像是个比较丑陋的解决办法。
有没有什么标准的方法可以在重新渲染表单时使用之前填写的文本,而不需要我这种丑陋的 try-except 解决方案呢?
请求的模板
{% block content %}
<div id="contact-generic-container">
<p>Lorem ipsum (not really, but ain't relevant).</p>
</div> <!-- #contact-generic-container -->
<div id="contact-form" class="clearfix">
<br/>
<h2>Kontakta oss!</h2>
<form action="/kontakt/" method="post">
{{ form.non_field_errors }}
<fieldset class="text">
{% csrf_token %}
<div class="field-wrapper">
<label for="id_name">Namn:</label>
{{ form.name }}
{{ form.name.errors }}
</div>
<div class="field-wrapper">
<label for="id_sender">E-post:</label>
{{ form.sender }}
{{ form.sender.errors }}
</div>
<div class="field-wrapper">
<label for="id_subject">Ämne:</label>
{{ form.subject }}
{{ form.subject.errors }}
</div>
</fieldset>
<fieldset class="text">
<div class="field-wrapper">
<label for="id_message">Meddelande:</label><br/>
{{ form.message }}
{{ form.message.errors }}
</div>
<div class="field-wrapper">
<label for="id_cc_myself">Kopia till mig själv:</label>
{{ form.cc_myself }}
{{ form.cc_myself.errors }}
</div>
<input type="submit" value="Skicka" />
<fieldset class="text">
</form>
</div>
{% endblock %}
1 个回答
2
这里有个简单的方法,可以让表单总是用POST数据初始化,或者什么都不初始化:
def contact(request):
form = ContactForm(request.POST or None)
if request.POST and form.is_valid():
然后去掉你的else部分。
这样表单里总会有数据,即使是GET请求也不会报错。
因为我用了点Python的小技巧,接下来我来解释一下。
- Python支持在表达式中使用和/或运算符。
- 当计算
or
时,Python会在第一个返回“真”的值时停止。 - 当计算
and
时,如果第一个条件返回“假”,Python会停止。
所以,当我们初始化表单时,我们让Python去赋值,要么是request.POST的值(如果它是真的),要么是None
(如果request.POST是假的,也就是空的)。这样在有POST请求时,表单就会正确地用request.POST里的值初始化,而在没有POST请求时则是None。
在我们的if语句中,如果request.POST是假的(也就是空的),Python就会在这里停止,不会调用form.is_valid()
,所以我们就不用担心在没有POST请求的情况下进行验证。
是不是很酷呢?