如何让 Django 视图返回表单错误
Posted
技术标签:
【中文标题】如何让 Django 视图返回表单错误【英文标题】:How to get Django view to return form errors 【发布时间】:2014-02-03 05:57:13 【问题描述】:这是我的看法:
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables =
'form': form
return render(request, 'main_page.html', variables)
这是我的 main_page.html:
% if form.errors %
<p>NOT VALID</p>
% for errors in form.errors %
errors
% endfor %
% endif %
<form method="post" action="/">% csrf_token %
<p><label for="id_username">Username:</label> form.username </p>
<p><label for="id_email">Email Address:</label> form.email </p>
<p><label for="id_password">Password:</label> form.password1 </p>
<p><label for="id_retypePassword">Retype Password:</label> form.password2 </p>
<input type="hidden" name="next" />
<input type="submit" value="Register" />
</form>
当我转到使用 main_page 视图的 url 时,它只显示表单。当我提交有错误的表单(带有空白字段且没有正确的电子邮件地址)时,它只会将我重定向到同一页面并且不显示任何错误。它甚至没有说“无效”。
当我改变时
% if form.errors %
到
% if not form.is_valid %
它总是说“无效”(即使这是第一次访问该 url,即使我还没有提交任何内容)。
这是我的注册表:
from django import forms
import re
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
class RegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=30)
email = forms.EmailField(label='Email')
password1 = forms.CharField(label='Password', widget=forms.PasswordInput())
password2 = forms.CharField(label='Password (Again)', widget=forms.PasswordInput())
def clean_password2(self):
if 'password1' in self.cleaned_data:
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if password1 == password2:
return password2
raise forms.ValidationError('Passwords do not match.')
def clean_username(self):
username = self.cleaned_data['username']
if not re.search(r'^\w+$', username): #checks if all the characters in username are in the regex. If they aren't, it returns None
raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
try:
User.objects.get(username=username) #this raises an ObjectDoesNotExist exception if it doesn't find a user with that username
except ObjectDoesNotExist:
return username #if username doesn't exist, this is good. We can create the username
raise forms.ValidationError('Username is already taken.')
【问题讨论】:
【参考方案1】:它会重定向你,因为如果方法是 POST,即使表单无效,你总是返回 HttpResponseRedirect
。试试这个:
def main_page(request):
form = RegistrationForm()
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables =
'form': form
return render(request, 'main_page.html', variables)
这样,调用is_valid
的表单实例被传递给模板,并且它有机会显示错误。只有当表单有效时,用户才会被重定向。如果您想花哨,请在重定向之前使用messages framework添加消息。
如果你想让它更简洁一点:
def main_page(request):
form = RegistrationForm(request.POST or None)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
return HttpResponseRedirect('/')
variables =
'form': form
return render(request, 'main_page.html', variables)
【讨论】:
对,这就是我最初所拥有的,但是“如果 request.method == 'POST'”但表单无效会发生什么?它仍然需要返回一些东西,对吗?我尝试了您的视图,如果表单无效,它会给出 ValueError,错误表示“main_page 视图没有返回 HttpResponse 对象”。 从我的理解中,我希望它始终重定向到主页,即使表单无效,因为这样我就可以在主页上显示表单中的错误,对吗?如果它是有效的,那很好。如果不是,它仍然很好,因为它会重定向到带有 form.errors 的主页,这是我的想法。这很奇怪,因为即使在我点击提交表单错误(使用我发布的视图)之后,模板也不会显示表单错误,所以就像视图没有意识到 request.method == 'POST'。 嗯,if request.method == "POST"
和not form.is_valid
,下面只是继续执行,最后返回render
函数的结果,所以它应该可以工作...?
如果出现错误,您不想重定向,因为通过重定向,您会丢失所有状态:HTTP is stateless。在浏览器将您的表单 POST 到服务器并且服务器以重定向响应后,浏览器不会 POST 到新的 url;它将发出一个 GET 请求。
啊,你是对的!当我说“对,这就是我最初拥有的”时,结果发现这并不是我最初拥有的。我最初有一个“else:variables = 'form':form return ....”,这就是为什么当request.method = =“POST”而不是form.is_valid时它给了我一个ValueError。好的,谢谢。【参考方案2】:
让你的视图变成这样:
if form.is_valid():
pass
# actions
else:
# form instance will have errors so we pass it into template
return render(request, 'template.html', 'form': form)
在模板中你可以遍历 form.errors 或简单:
forms.as_p
【讨论】:
对,但是如果 request.method != "POST" 也有可能(因为它是我的主页,所以如果这是用户第一次访问主页,那么他没有'还没有提交任何东西,所以 request.method != "POST" 对吗? 是的,请求方法是 GET。我建议您看一下基于 django 类的视图。这是一个没有脏if request.method == POST
等的表单验证的快速示例:pastebin.com/D5YwFLpP如果用户第一次打开页面方法get
将显示表单。如果用户提交表单方法post
将对其进行验证并做出适当的操作。【参考方案3】:
您可以重新格式化视图以在控制台中显示表单错误,如下所示
def main_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.clean_data['username'],
password=form.clean_data['password1'],
email=form.clean_data['email']
)
else:
print(form.errors)
return HttpResponse("Form Validation Error")
return HttpResponseRedirect('/')
else:
form = RegistrationForm()
variables =
'form': form
return render(request, 'main_page.html', variables)
与往常一样,保持上述缩进。如果表单有任何错误,它将显示在控制台中,如
<ul class="errorlist"><li>date<ul class="errorlist"><li>Enter a valid date.</li></ul></li></ul>
希望对你有帮助
【讨论】:
以上是关于如何让 Django 视图返回表单错误的主要内容,如果未能解决你的问题,请参考以下文章
如何让来自 Ajax 的 Django 表单错误出现在用户屏幕上?
在 Django 中,如何通过错误返回 File 输入的值?
如何在我的 Django 应用程序的“评论”视图中修复此错误?