Django表单验证没有重定向到正确的URL

时间:2016-08-10 23:48:26

标签: python django validation

我使用Django 1.9.8并且在验证用于注册用户的表单时遇到了一些麻烦。如果存在验证错误,则重定向回到表单是不正确的URL。注册网址为localhost:8000/register。如果发现错误(无论如何,我认为发生了什么),页面将重定向到localhost:8000/register/register。我做错了什么导致重定向向网址添加额外的register参数?

#authorization/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') #show list of users after saving
        else:
            #return to the form for the user to fix errors & continue registering
            return render(request, 'authorization/register.html', {'form': RegisterForm}) 

这里是RegisterForm内容

#authorization/forms.py
class RegisterForm(AuthenticationForm):
    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'}))

    def clean_password(self):
        password1 = self.cleaned_data.get('password')
        password2 = self.cleaned_data.get('repassword')
        if password1 and password1 != password2:
            raise forms.ValidationError("Passwords don't match")
        return self.cleaned_data

我不确定这是否相关,但这是我的urls.py

#authorization/urls.py
urlpatterns = [
    url(r'^$', views.home, name='home'),
    url(r'^register/', views.RegisterViewSet.as_view({'get' : 'register', 'post' : 'create'})),
]

我在添加表单验证部分之前测试了create方法,并且它成功地保存了用户,所以我知道它至少已经达到了这一点。

修改 - 添加表单内容

{% if form.errors %}
    {% 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="register" 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>

1 个答案:

答案 0 :(得分:0)

表单上的action指向相对路径register。如果url路径不以斜杠开头,它将在当前url的最后一个斜杠后附加它。由于表单已发布到/register/register,并且您的网址格式与之匹配,因此这是您在发生错误时会看到的网址。

要解决此问题,您应该将其设为绝对网址(以斜杠开头)或将其设为空(即action='')以发布到当前网址。

将动作指向RegisterViewSet的最有效方法是使用{% url %}模板标记。要使用此功能,您需要为URL指定名称。向模式添加$也是一个好主意,因此只有在/register/是完整网址的情况下才会匹配,如果它只是网址的开头则不匹配:

# authorization/urls.py
urlpatterns = [
    url(r'^$', views.home, name='home'),
    url(r'^register/$', views.RegisterViewSet.as_view({'get' : 'register', 'post' : 'create'}), name='register'),
]

# authorization/register.html
<form method="post" action="{% url 'register' %}" id="RegisterForm">
...