Django注册未提示用户已存在问题排查及修复请求
问题原因
你的代码中,username和email在模型里设置了unique=True,但表单层面没提前做唯一性校验,而是等到调用Account.objects.create_user()时才触发数据库的唯一约束。同时视图未捕获数据库抛出的IntegrityError异常,导致异常发生后,表单无法将错误信息传递到前端,只会重新渲染注册表单,所以看不到用户已存在的提示。
修复方案
推荐在表单类中添加字段级校验逻辑,提前在表单验证阶段检查用户名和邮箱是否已存在,错误会自动添加到表单的错误信息中,前端可直接渲染显示。
修改表单代码
在RegistrationForm类中新增clean_username和clean_email方法,同时补全clean方法的返回值:
class RegistrationForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={ 'placeholder': 'Enter Password', 'class': 'form-control' })) confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={ 'placeholder': 'Confirm Password', 'class': "form-control" })) class Meta: model = Account fields = ['username', 'sex', 'email', 'password'] def __init__(self, *args, **kwargs): super(RegistrationForm, self).__init__(*args, **kwargs) for field in self.fields: self.fields[field].widget.attrs['class'] = 'form-control' def clean(self): cleaned_data = super(RegistrationForm, self).clean() password = cleaned_data.get('password') confirm_password = cleaned_data.get('confirm_password') if password != confirm_password: raise forms.ValidationError('Password does not match!') return cleaned_data # 必须返回清理后的数据,否则后续校验会丢失数据 def clean_username(self): username = self.cleaned_data.get('username') if Account.objects.filter(username=username).exists(): raise forms.ValidationError('Username already exists!') return username def clean_email(self): email = self.cleaned_data.get('email') if Account.objects.filter(email=email).exists(): raise forms.ValidationError('Email already exists!') return email
可选:视图异常处理(不推荐)
若不想修改表单,也可在视图中捕获IntegrityError,手动将错误添加到表单:
from django.db import IntegrityError def register(request): if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): username = form.cleaned_data['username'] email = form.cleaned_data['email'] password = form.cleaned_data['password'] sex = form.cleaned_data['sex'] try: user = Account.objects.create_user(username=username, email=email, password=password, sex=sex) user.save() messages.success(request, 'Udało Ci się zarejestrować!') return redirect('register') except IntegrityError as e: # 根据错误信息判断是用户名还是邮箱重复 if 'username' in str(e): form.add_error('username', 'Username already exists!') elif 'email' in str(e): form.add_error('email', 'Email already exists!') else: form.add_error(None, 'User already exists!') context = {'form': form} return render(request, 'accounts/register.html', context) else: form = RegistrationForm() context = {'form': form} return render(request, 'accounts/register.html', context)
这种方式依赖数据库错误信息,可靠性和规范性不如表单层面校验,仅作备选。
前端错误渲染
确保register.html模板中正确渲染表单错误:
{% if form.errors %} {% for field in form %} {% for error in field.errors %} <div class="alert alert-danger"> {{ error }} </div> {% endfor %} {% endfor %} {% for error in form.non_field_errors %} <div class="alert alert-danger"> {{ error }} </div> {% endfor %} {% endif %} <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Register</button> </form>
内容的提问来源于stack exchange,提问作者Trollol45
相关产品推荐
相关产品推荐

