我使用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>
答案 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">
...