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')
解决方案
错误原因
- Django中一对一关联的反向属性默认是小写的模型名称,即
user.account而不是user.Account。 - 更关键的是,创建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
相关产品推荐
相关产品推荐

