英文:
Django KeyError at forms.py
问题
Here is the translated content without the code:
我正在学习Django,正在尝试使用表单注册用户。当我填写用户名、电子邮件、密码和确认密码字段后,提交注册表单时出现错误,错误信息如下:
KeyError at director/register/ "confirm_password"
然而,当我查看错误消息中的POST数据时,我明确看到了我要访问的数据。
csrfmiddlewaretoken: blahblahblabh
username: dasdasd
email: dasd@dsada.com
password: test123!
confirm_password: test123!
以下是forms.py、views.py和register.html文件的部分内容。
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ("email", "password")
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ("email", "password")
class RegisterUser(forms.Form):
username = forms.CharField(max_length=64, required=True)
email = forms.EmailField()
password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
confirm_password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
def clean_username(self):
username = self.cleaned_data["username"]
if CustomUser.objects.filter(username=username).exists():
raise forms.ValidationError("Email already exists")
return username
def clean_email(self):
email = self.cleaned_data['email']
if CustomUser.objects.filter(email=email).exists():
raise forms.ValidationError("Email already exists")
return email
def clean_password(self):
password = self.cleaned_data['password']
confirm_password = self.cleaned_data['confirm_password']
if password != confirm_password:
raise forms.ValidationError("Passwords do not match")
return password
views.py(register_view)
def register_view(request):
if request.method == "POST":
form = RegisterUser(request.POST)
if form.is_valid():
new_user = form.save()
login(request, new_user)
return redirect('home')
else:
form = RegisterUser()
return render(request, 'pokedex/register.html', {'form': form})
register.html
{% extends 'pokedex/layout.html' %}
{% block title %}Register{% endblock title %}
{% block body %}
<h1>Register</h1>
{% if form.errors %}
<div class="alert alert-danger">
<ul>
{% for error in form.errors.values %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Register">
</form>
{% endblock body %}
EDIT: 添加了Traceback
环境:
请求方法:POST
请求URL:http://127.0.0.1:8000/pokedex/register/
Django版本:4.1.7
Python版本:3.9.2
已安装应用程序:
['pokedex',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
已安装中间件:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback(最新调用最前):
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\core\handlers\exception.py”,行 56,在inner
response = get_response(request)
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\core\handlers\base.py”,行 197,在_get_response
response = wrapped_callback(request,* callback_args,** callback_kwargs)
File “C:\Users\Alice\Documents\Code\stepchallenge\pokedex\views.py”,行 45,在register_view
if form.is_valid():
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py”,行 205,在is_valid
return self.is_bound and not self.errors
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py”,行 200,在errors
self.full_clean()
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py”,行 437,在full_clean
self._clean_fields()
File “C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py”,行 452,在_clean_fields
value = getattr(self,“clean_%s”%name)()
File “C:\Users\Alice\Documents\Code\stepchallenge\pokedex\forms.py”,行 38,在clean_password
confirm_password = self.cleaned_data['confirm_password']
异常类型:KeyError at /pokedex/register/
异常值:'confirm_password'
英文:
I'm learning django and I'm playing around with forms and registering users.
When I submit the registration form with the username, email, password, and confirm password fields filled, I get an error that states:
KeyError at director/register/
"confirm_password"
However, when I look at the POST data in the error message I clearly see the data I'm trying to access.
csrfmiddlewaretoken: blahblahblabh
username: dasdasd
email: dasd@dsada.com
password: test123!
confirm_password: test123!
Below are the forms.py, portion of the views.py, register.html files.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ("email", "password")
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ("email", "password")
class RegisterUser(forms.Form):
username = forms.CharField(max_length=64, required=True)
email = forms.EmailField()
password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
confirm_password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
def clean_username(self):
username = self.cleaned_data["username"]
if CustomUser.objects.filter(username=username).exists():
raise forms.ValidationError("Email already exists")
return username
def clean_email(self):
email = self.cleaned_data['email']
if CustomUser.objects.filter(email=email).exists():
raise forms.ValidationError("Email already exists")
return email
def clean_password(self):
password = self.cleaned_data['password']
confirm_password = self.cleaned_data['confirm_password']
if password != confirm_password:
raise forms.ValidationError("Passwords do not match")
return password```
views.py (register_view)
def register_view (request):
if request.method == "POST":
form = RegisterUser(request.POST)
if form.is_valid():
new_user = form.save()
login(request, new_user)
return redirect('home')
else:
form = RegisterUser()
return render(request, 'pokedex/register.html', {'form': form})
register.html
{% extends 'pokedex/layout.html' %}
{% block title %}Register{% endblock title %}
{% block body %}
<h1>Register</h1>
{% if form.errors %}
<div class="alert alert-danger">
<ul>
{% for error in form.errors.values %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Register">
</form>
{% endblock body %}
EDIT: Added Traceback
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/pokedex/register/
Django Version: 4.1.7
Python Version: 3.9.2
Installed Applications:
['pokedex',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\core\handlers\exception.py", line 56, in inner
response = get_response(request)
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Alice\Documents\Code\stepchallenge\pokedex\views.py", line 45, in register_view
if form.is_valid():
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py", line 205, in is_valid
return self.is_bound and not self.errors
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py", line 200, in errors
self.full_clean()
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py", line 437, in full_clean
self._clean_fields()
File "C:\Users\Alice\Documents\Code\env\lib\site-packages\django\forms\forms.py", line 452, in _clean_fields
value = getattr(self, "clean_%s" % name)()
File "C:\Users\Alice\Documents\Code\stepchallenge\pokedex\forms.py", line 38, in clean_password
confirm_password = self.cleaned_data['confirm_password']
Exception Type: KeyError at /pokedex/register/
Exception Value: 'confirm_password'
答案1
得分: 0
按照Django官方文档中的描述,在Forms部分的Cleaning and validating fields that depend on each other章节中,你不能在clean_password
函数内部读取self.cleaned_data['confirm_password']
,因为该字段可能尚未填充。
我建议你通过以下方式来进行验证,覆盖clean
函数,像这样:
class RegisterForm(forms.Form):
username = forms.CharField(max_length=64, required=True)
email = forms.EmailField()
password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
confirm_password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
def clean_username(self):
username = self.cleaned_data["username"]
if CustomUser.objects.filter(username=username).exists():
raise forms.ValidationError("Email already exists")
return username
def clean_email(self):
email = self.cleaned_data['email']
if CustomUser.objects.filter(email=email).exists():
raise forms.ValidationError("Email already exists")
return email
# 移除clean_password函数以使用默认验证
# 在所有字段都被清理后检查密码
def clean(self):
cleaned_data = super().clean()
password = cleaned_data['password']
confirm_password = cleaned_data['confirm_password']
if password != confirm_password:
raise forms.ValidationError("Passwords do not match")
我还建议你查看Django官方文档 - Forms,因为它描述了如何避免大多数错误。
英文:
As described in the Django official documentation in the section Forms at Cleaning and validating fields that depend on each other, you cannot read self.cleaned_data['confirm_password']
inside the function clean_password
, as the field might not be populated yet.
I suggest you to do the validation overriding the clean
function like this:
class RegisterForm(forms.Form):
username = forms.CharField(max_length=64, required=True)
email = forms.EmailField()
password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
confirm_password = forms.CharField(max_length=128, widget=forms.PasswordInput(), required=True)
def clean_username(self):
username = self.cleaned_data["username"]
if CustomUser.objects.filter(username=username).exists():
raise forms.ValidationError("Email already exists")
return username
def clean_email(self):
email = self.cleaned_data['email']
if CustomUser.objects.filter(email=email).exists():
raise forms.ValidationError("Email already exists")
return email
# Removed clean_password function to use the default validation
# Moved password check after all field are cleaned
def clean(self):
cleaned_data = super().clean()
password = cleaned_data['password']
confirm_password = cleaned_data['confirm_password']
if password != confirm_password:
raise forms.ValidationError("Passwords do not match")
I suggest also to take a look to Django official documentation - Forms as it describes how to avoid most errors.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论