【问题标题】:How to get Django view to return form errors如何让 Django 视图返回表单错误
【发布时间】: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.')

【问题讨论】:

    标签: django forms django-views django-authentication django-registration


    【解决方案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>
    

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-23
      • 1970-01-01
      • 1970-01-01
      • 2018-01-08
      相关资源
      最近更新 更多