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

Django 4.2扩展User模型后,注册时如何为Account模型赋值?

问题

在Django 4.2版本中,我通过名为Account的模型扩展了内置User模型,Django管理面板已成功展示该模型且功能正常。但在用户注册时尝试为Account模型的mobile_number字段赋值时,出现错误:AttributeError at /accounts/create 'User' object has no attribute 'Account'。

相关代码如下:

models.py

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

class Account(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    mobile_number = models.CharField(max_length=10)
    def __str__(self):
        return f"{self.user.username} ({self.user.first_name})"

admin.py

from django.contrib import admin
from accounts.models import Account
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

# Register your models here.
class AccountInline(admin.StackedInline):
    model = Account
    can_delete = False
    verbose_name_plural = 'Accounts'

class CustomisedUserAdmin (UserAdmin):
    inlines = (AccountInline, )

admin.site.unregister(User)
admin.site.register(User, CustomisedUserAdmin) 
admin.site.register(Account)

views.py

def register(request):
    if request.method == "POST":
        username = request.POST['username']
        first_name = request.POST['first_name']
        last_name = request.POST['last_name']
        email = request.POST['email']
        password1 = request.POST['password1']
        password2 = request.POST['password2']
        mobile_number = request.POST['mobile_number']
        if password1 == password2:
            if User.objects.filter(email=email).exists():
                messages.info(request, "Email already registered")
                return redirect('register')
            elif User.objects.filter(username=username).exists():
                messages.info(request, "Username already registered")
                return redirect('register')
            else:
                user = User.objects.create_user(username=username, first_name=first_name, last_name=last_name, email=email, password=password1)
                mobile_number = user.Account.mobile_number
                user.save();
                return redirect('login')
        else:
            messages.info(request, "Password not the same")
            return redirect('register')
    else:    
        return render(request, 'register.html')
解决方案

错误原因

  1. Django中一对一关联的反向属性默认是小写的模型名称,即user.account而不是user.Account。
  2. 更关键的是,创建User实例后并没有自动生成对应的Account实例,直接访问反向关联会触发AttributeError。

修正代码

修改views.py中的注册逻辑,在创建User后手动创建Account实例并绑定:

def register(request):
    if request.method == "POST":
        username = request.POST['username']
        first_name = request.POST['first_name']
        last_name = request.POST['last_name']
        email = request.POST['email']
        password1 = request.POST['password1']
        password2 = request.POST['password2']
        mobile_number = request.POST['mobile_number']
        if password1 == password2:
            if User.objects.filter(email=email).exists():
                messages.info(request, "Email already registered")
                return redirect('register')
            elif User.objects.filter(username=username).exists():
                messages.info(request, "Username already registered")
                return redirect('register')
            else:
                # 创建User实例
                user = User.objects.create_user(
                    username=username, 
                    first_name=first_name, 
                    last_name=last_name, 
                    email=email, 
                    password=password1
                )
                # 创建关联的Account实例并设置手机号
                Account.objects.create(user=user, mobile_number=mobile_number)
                # User已创建完成,无需再次save
                return redirect('login')
        else:
            messages.info(request, "Password not the same")
            return redirect('register')
    else:    
        return render(request, 'register.html')

额外说明

  • 后续如果需要通过User实例访问Account,使用user.account(全小写模型名)即可,比如user.account.mobile_number。
  • 也可以在Account模型的OneToOneField中添加related_name参数自定义反向关联名称,例如:
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    
    之后就可以用user.profile访问Account实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 18:05:28