You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:17:39