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

Django扩展User模型字段无法保存至MongoDB问题求助

问题:Django扩展User模型后额外字段无法保存到MongoDB

问题详情

扩展Django内置User模型,添加了company_name和role字段,但通过注册表单创建用户时,这两个字段无法保存到MongoDB数据库。提交表单后用户能正常创建,且表单已正确捕获这些字段(通过打印form.cleaned_data确认),但数据库文档中没有这两个字段。

用户提供的代码如下:

forms.py

from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django import forms
from django.forms.widgets import PasswordInput, TextInput
from django.core.exceptions import ValidationError

class CreateUserForm(UserCreationForm):
    company_name = forms.CharField(max_length=100)
    role = forms.CharField(max_length=100)
    email = forms.EmailField(required=True)

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email and email.endswith('@gmail.com'):
            raise ValidationError("Gmail addresses are not allowed.")
        return email

    class Meta:
        model = User
        fields = ['username', 'email','company_name', 'role', 'password1', 'password2']
    
    def save(self, commit=True):
        user = super(CreateUserForm, self).save(commit=False)
        user.company_name = self.cleaned_data['company_name']
        user.role = self.cleaned_data['role']
        if commit:
            user.save()
        return user

class LoginForm(AuthenticationForm):
    username = forms.CharField(widget=TextInput())
    password = forms.CharField(widget=PasswordInput())

views.py

from django.shortcuts import render, redirect
from . forms import CreateUserForm, LoginForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import auth
from django.contrib.auth import authenticate, login, logout

def homepage(request):
    return render(request, 'loginapp/index.html')

def signupPage(request):
     form = CreateUserForm()
     if request.method == "POST":
        form = CreateUserForm(request.POST)
        if form.is_valid():
            print("Form data:", form.cleaned_data)
            form.save()
            return redirect("loginPage")
     context = {'registerform':form}
     return render(request, 'loginapp/signupPage.html', context=context)

def loginPage(request):
    form = LoginForm()
    if request.method == 'POST':
        form = LoginForm(request, data=request.POST)
        if form.is_valid():
            username = request.POST.get('username')
            password = request.POST.get('password')
            user = authenticate(request, username=username, password=password)
            if user is not None:
                auth.login(request, user)
                return redirect("dashboard")
    context = {'loginform':form}
    return render(request, 'loginapp/loginPage.html', context=context)

def user_logout(request):
    auth.logout(request)
    return redirect("")

@login_required(login_url="loginPage")
def dashboard(request):
    return render(request, 'loginapp/dashboard.html')

原因分析

核心问题在于:你的表单仍然绑定了Django默认的User模型,而非你自己扩展的用户模型。

默认User模型并没有company_name和role字段,即使你在表单中添加了这些字段并赋值给user对象,Django ORM也不会将这些未在模型中定义的字段保存到数据库(包括MongoDB)。这就是为什么数据库文档中看不到这两个字段的原因。

解决方案

需要创建自定义用户模型并配置Django使用该模型,步骤如下:

1. 创建自定义用户模型

在应用的models.py中定义继承AbstractUser的自定义用户模型,添加所需字段:

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    company_name = models.CharField(max_length=100)
    role = models.CharField(max_length=100)

2. 配置Django使用自定义用户模型

在项目的settings.py中添加以下配置(替换为你的应用名):

AUTH_USER_MODEL = 'loginapp.CustomUser'

注意:该配置必须在执行第一次migrate前设置。如果已经执行过迁移,需要重置数据库(删除现有迁移文件和数据库)后重新执行迁移。

3. 修改表单绑定自定义模型

更新forms.py,使用get_user_model()获取自定义用户模型,避免硬编码:

from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth import get_user_model
from django import forms
from django.forms.widgets import PasswordInput, TextInput
from django.core.exceptions import ValidationError

# 获取自定义用户模型
User = get_user_model()

class CreateUserForm(UserCreationForm):
    email = forms.EmailField(required=True)

    def clean_email(self):
        email = self.cleaned_data.get('email')
        if email and email.endswith('@gmail.com'):
            raise ValidationError("Gmail addresses are not allowed.")
        return email

    class Meta:
        model = User
        fields = ['username', 'email','company_name', 'role', 'password1', 'password2']
    
    def save(self, commit=True):
        user = super().save(commit=False)
        user.email = self.cleaned_data['email']
        # 显式赋值额外字段(可选,因为fields中已包含,super().save会自动处理)
        user.company_name = self.cleaned_data['company_name']
        user.role = self.cleaned_data['role']
        if commit:
            user.save()
        return user

class LoginForm(AuthenticationForm):
    username = forms.CharField(widget=TextInput())
    password = forms.CharField(widget=PasswordInput())

4. 执行数据库迁移

运行以下命令创建并应用迁移:

python manage.py makemigrations
python manage.py migrate

验证

重新运行项目,提交注册表单后,MongoDB中的用户文档应该会包含company_name和role字段。

内容的提问来源于stack exchange,提问作者Huzaifa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:54:55