在POST数据中缺少Django表单输入

时间:2016-08-11 18:27:50

标签: python django django-forms django-templates

我正在使用Django 1.9.8,我正在尝试学习如何使用表单验证。我正在编写用于注册用户的表单。我遇到了两个问题。

  1. 在forms.py文件方法中无法访问重新输入密码的字段(相反,根本不存在)。当我使用raise Exception(self.cleaned_data.get('password'))查看内容时,会显示密码。我还可以查看用户名和电子邮件。当我对repassword字段执行相同操作时,会显示None 编辑 - 这是通过更改forms.py文件以使用clean()方法来解决的

  2. 我的表单上根本没有显示验证错误。如果有错误,重定向返回到表单工作,但输入中没有任何内容供用户修复,也不显示错误。 编辑 - 通过在else语句后更改RegisterForm调用解决form = RegisterForm(request.POST)

  3. 这是forms.py文件

    #forms.py
    class RegisterForm(forms.Form):
        username = forms.CharField(label="Username", max_length=30,
                                   widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'username'}))
        email = forms.CharField(label="Email", max_length=30,
                                   widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'email'}))
        password = forms.CharField(label="Password", max_length=30,
                                   widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'password', 'type' : 'password'}))
        repassword = forms.CharField(label="RePassword", max_length=30,
                                   widget=forms.TextInput(attrs={'class': 'form-control', 'name': 'repassword', 'type' : 'password'}))
    
        #Edit - this was changed to the clean() function in the selected answer.
        def clean_password(self):
            password1 = self.cleaned_data.get('password')
            password2 = self.cleaned_data.get('repassword')
            #raise Exception(self.cleaned_data.get('repassword')) # None is displayed
    
            if password1 and password1 != password2:
                raise forms.ValidationError("Passwords don't match")
            return self.cleaned_data
    

    这是表单模板

    #register.html
    
    {% if form.errors %}
        <h2>ERROR!</h2>
        {% for field in form %}
            {% for error in field.errors %}
                <div class="alert alert-error">
                    <strong>{{ error|escape }}</strong>
                </div>
            {% endfor %}
        {% endfor %}
    {% endif %}
    
    <form method="post" action="" id="RegisterForm">
    {% csrf_token %}
        <p class="bs-component">
            <table>
                <tr>
                    <td>{{ form.username.label_tag }}</td>
                    <td>{{ form.username }}</td>
                </tr>
                <tr>
                    <td>{{ form.email.label_tag }}</td>
                    <td>{{ form.email }}</td>
                </tr>
                <tr>
                    <td>{{ form.password.label_tag }}</td>
                    <td>{{ form.password }}</td>
                </tr>
                 <tr>
                    <td>{{ form.repassword.label_tag }}</td>
                    <td>{{ form.repassword }}</td>
                </tr>
            </table>
        </p>
        <p class="bs-component">
            <center>
                <input class="btn btn-success btn-sm" type="submit" value="Register" />
            </center>
        </p>
        <input type="hidden" name="next" value="{{ next }}" />
    </form>
    

    这是视图

    #views.py
    class RegisterViewSet(viewsets.ViewSet):
    
        #GET requests
        def register(self,request):
            return render(request, 'authorization/register.html', {'form': RegisterForm})
    
        #POST requests
        def create(self,request):
            form = RegisterForm(request.POST)
            if form.is_valid():
                username = request.POST['username']
                email = request.POST['email']
                password = request.POST['password']
                user = User.objects.create_user(username,email,password)
                user.save()
                return HttpResponseRedirect('/users')
            else:
                return render(request, 'authorization/register.html', {'form': RegisterForm })
                #changed the previous line to the following. This fixed the errors not displaying
                #return render(request, 'authorization/register.html', {'form': RegisterForm(request.POST) }) 
    

1 个答案:

答案 0 :(得分:2)

我不确定{100}确保self.cleaned_data.get('repassword')在该方法中返回None的原因,但是clean_password不适合执行相互依赖的字段的验证。

根据docs,您应该在clean()函数中执行此类验证:

<强> views.py

def register(self,request):
    form = RegisterForm() # Notice `()` at the end
    return render(request, 'authorization/register.html', {'form': form})

<强> forms.py

...

def clean(self):
    cleaned_data = super(RegisterForm, self).clean()

    password1 = cleaned_data.get('password')
    password2 = cleaned_data.get('repassword')

    if password1 and password1 != password2:
        raise forms.ValidationError("Passwords don't match")

请注意,您不必实施clean_passwordclean_repassword

(如果您认为仍需要实施clean_password,则必须从password1返回self.cleaned_data

您还需要按照docs

中的说明正确呈现表单错误

不要忘记将其添加到您的模板中:

{{ form.non_field_errors }}

至于第二个错误,问题是,每次验证失败时,您都会返回一个新的RegisterForm实例而不是无效的实例。

您应该更改create()功能中的一行:

return render(request, 'authorization/register.html', {'form': RegisterForm}) 

到此:

return render(request, 'authorization/register.html', {'form': form})