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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:46:23