Django用户注册表单验证报错及自定义字段校验需求
解决Django注册功能的FieldError及相关问题
嘿,我来帮你搞定这个问题!你遇到的FieldError核心原因很明确:你把mobile和org_name字段放在了单独的UserRegForm模型里,但在表单的校验逻辑中,却错误地去User模型里查找mobile字段——Django自带的User模型(或者你自定义的User模型)本身并没有mobile这个字段,所以才会抛出"Cannot resolve keyword 'mobile' into field"的错误。
接下来我会一步步帮你修正代码,实现你需要的注册功能(用户名、邮箱、手机号、密码、组织名称,且邮箱/手机号重复时提示错误):
1. 修正模型与表单的关联逻辑
你的UserRegForm模型是和User一对一关联的,所以注册流程应该是:先创建User实例,再创建对应的UserRegForm实例来存储手机号和组织名称。因此,RegistrationForm不应该继承ModelForm(因为它要处理两个模型的字段),改成普通的forms.Form更合适。
修改后的forms.py
from django import forms from django.contrib.auth import get_user_model, authenticate from .models import UserRegForm User = get_user_model() class UserLoginForm(forms.Form): email = forms.EmailField(label='Email address') password = forms.CharField(label='Password', widget=forms.PasswordInput()) def clean(self, *args, **kwargs): email = self.cleaned_data.get("email") password = self.cleaned_data.get("password") if email and password: # 注意:默认User模型的authenticate是用username,若用邮箱登录,需在settings配置认证后端 user = authenticate(username=email, password=password) if not user: raise forms.ValidationError("This email id is not registered") if not user.check_password(password): raise forms.ValidationError("Incorrect password") return super(UserLoginForm, self).clean(*args, **kwargs) class RegistrationForm(forms.Form): username = forms.CharField(label='Username') email = forms.EmailField(label='Email address') mobile = forms.CharField(label='Mobile No', max_length=10) password = forms.CharField(label='Password', widget=forms.PasswordInput()) org_name = forms.CharField(label='Organisation Name') def clean_email(self): email = self.cleaned_data.get('email') # 检查User模型中是否已有该邮箱 if User.objects.filter(email=email).exists(): raise forms.ValidationError("This email id is already registered") return email def clean_mobile(self): mobile = self.cleaned_data.get('mobile') # 检查UserRegForm模型中是否已有该手机号(字段存在于此模型) if UserRegForm.objects.filter(mobile=mobile).exists(): raise forms.ValidationError("This mobile no is already registered") return mobile
2. 修正视图中的注册逻辑
你的signup视图有两个关键错误:
user=set_password(password):set_password是User实例的方法,正确用法是user.set_password(password),直接赋值会把user变成None,导致后续报错。- 没有创建
UserRegForm实例来存储手机号和组织名称。
修改后的views.py
from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login, get_user_model from .forms import UserLoginForm, RegistrationForm from .models import UserRegForm User = get_user_model() def login_view(request): # 避免和django内置login重名,改为login_view更安全 title = "Login" form = UserLoginForm(request.POST or None) if form.is_valid(): email = form.cleaned_data.get("email") password = form.cleaned_data.get("password") user = authenticate(username=email, password=password) if user: login(request, user) return redirect("/") # 可替换为登录后跳转的目标页面 return render(request, "userRegistration/login.html", {"form": form, "title": title}) def signup(request): title = "Signup" if request.method == "POST": form = RegistrationForm(request.POST) if form.is_valid(): # 1. 创建User实例 username = form.cleaned_data.get("username") email = form.cleaned_data.get("email") password = form.cleaned_data.get("password") user = User.objects.create_user(username=username, email=email, password=password) # 2. 创建UserRegForm实例,关联到新用户 mobile = form.cleaned_data.get("mobile") org_name = form.cleaned_data.get("org_name") UserRegForm.objects.create(email=user, mobile=mobile, org_name=org_name) # 3. 登录新用户 new_user = authenticate(username=email, password=password) login(request, new_user) return redirect("userRegistration:a") # 替换为你定义的url名称 else: form = RegistrationForm() return render(request, "userRegistration/signup.html", {"form": form, "title": title})
3. 修复HTML模板的语法错误
你的模板里有两个小问题:多了一个{% endif %},还有action属性里的双引号重复。
修改后的signup.html
{% block title %}Registration{% endblock %} {% block content %} <h1>Registration</h1> {% if form.errors %} <h2>Please fix the following errors:</h2> {{ form.errors }} {% endif %} <form method="post" action="{% url 'userRegistration:signup' %}"> {% csrf_token %} {{ form.as_p }} <!-- 用as_p优化表单排版,也可自定义渲染每个字段 --> <input type="submit" name="submit" value="Sign Up" /> </form> {% endblock %}
额外注意事项
- 如果使用自定义User模型,确保在settings.py中正确配置
AUTH_USER_MODEL。 - 若要完全支持邮箱登录,可在settings.py添加自定义认证后端:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', # 'yourapp.backends.EmailBackend', # 需自行实现该后端 ]
内容的提问来源于stack exchange,提问作者Dinesh Kumar
相关产品推荐
相关产品推荐

