如何在Django扩展用户模型UserProfile中检测手机号重复
解决Django手机号重复检测的问题&修正代码错误
嗨,我来帮你搞定这个手机号重复检测的问题,顺便修正你代码里的几个小错误~
首先先指出你原视图代码里的几个问题:
- 字段名不匹配:你的
UserProfile模型里手机号字段是Mobile(大写M),但视图里写的是mobile(小写m),Django会找不到这个字段哦 - 关联查询错误:要检测手机号是否存在,直接查询
UserProfile模型就可以了,不需要通过User反向关联查(而且User.userprofile这种写法本身也不对,反向关联的正确用法是针对单个User实例,比如some_user.userprofile,但这里我们要查所有手机号,直接查模型就行) - 拼写错误:
exsist()应该是exists(),少写了一个字母s
下面给你两种解决方案,推荐第二种更符合Django最佳实践的写法:
方案一:直接修正视图里的查询代码
先确保你已经导入了UserProfile模型,然后把视图里的错误判断代码改成下面这样:
# 记得先导入模型 from .models import UserProfile def signup(request): if request.method == "POST": form = signupForm(request.POST) userprofile_form = UserProfileForm(request.POST) if form.is_valid() and userprofile_form.is_valid(): First_Name = form.cleaned_data['Name'] email = form.cleaned_data['email'] password = form.cleaned_data['password'] mobile = userprofile_form.cleaned_data['Mobile'] # 检测邮箱是否已存在 if User.objects.filter(username=email).exists() or User.objects.filter(email=email).exists(): print("Email id is already taken") # 修正后的手机号检测逻辑 elif UserProfile.objects.filter(Mobile=mobile).exists(): print("Mobile Number already taken ") # 验证通过后创建用户和Profile else: user = User.objects.create_user(username=email, email=email, password=password) user.first_name = First_Name user.save() # 关联UserProfile profile = userprofile_form.save(commit=False) profile.user = user profile.save() # 这里可以添加跳转逻辑,比如跳转到登录页 # return redirect('login') else: form = signupForm() userprofile_form = UserProfileForm() return render(request, 'your_signup_template.html', {'form': form, 'userprofile_form': userprofile_form})
方案二:推荐!把验证逻辑放到表单里(更规范)
Django的表单本身就支持自定义验证逻辑,把手机号唯一性检测放到UserProfileForm里,这样视图代码会更简洁,而且错误信息可以直接返回给前端页面,用户体验更好。
修改你的UserProfileForm:
class UserProfileForm(forms.ModelForm): Mobile = forms.CharField( widget=forms.TextInput(attrs={'class': 'myinput', 'placeholder':'Mobile Number','title':'Please Enter Phone Number Without Country Code, Eg:9999999999 '}), min_length=10, max_length=15, required=True, validators=[clean_phone, ] ) class Meta: model = UserProfile fields=('Mobile',) def __init__(self, *args, **kwargs): super(UserProfileForm, self).__init__(*args, **kwargs) self.fields['Mobile'].widget.attrs.update({'class' : 'myinput' ,'placeholder':'Mobile Number','title':'Please Enter Phone Number Without Country Code, Eg:9999999999 '}) # 添加自定义手机号验证方法 def clean_Mobile(self): mobile = self.cleaned_data.get('Mobile') # 检查当前手机号是否已存在于UserProfile中 if UserProfile.objects.filter(Mobile=mobile).exists(): raise forms.ValidationError("Mobile Number already taken") return mobile
然后你的视图代码就可以简化了,不需要再手动判断手机号,只要检查表单是否有效就行:
def signup(request): if request.method == "POST": form = signupForm(request.POST) userprofile_form = UserProfileForm(request.POST) if form.is_valid() and userprofile_form.is_valid(): # 所有验证都通过了,直接创建用户和Profile First_Name = form.cleaned_data['Name'] email = form.cleaned_data['email'] password = form.cleaned_data['password'] user = User.objects.create_user(username=email, email=email, password=password) user.first_name = First_Name user.save() profile = userprofile_form.save(commit=False) profile.user = user profile.save() # 跳转逻辑 # return redirect('login') # 如果表单无效,前端会自动显示错误信息(包括手机号重复的错误) else: form = signupForm() userprofile_form = UserProfileForm() return render(request, 'your_signup_template.html', {'form': form, 'userprofile_form': userprofile_form})
这样不仅代码更整洁,还能让错误信息直接在表单对应的输入框下方显示,比只在控制台打印要友好得多~
内容的提问来源于stack exchange,提问作者Naveenkumar A
相关产品推荐
相关产品推荐

