我有一个扩展User
的类,这样我也可以存储物理地址。
from django.contrib.auth.models import User
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
street = models.CharField(max_length=80, default="")
post_name = models.CharField(max_length=80, default=None)
post_number = models.IntegerField(default=None)
sqlite 数据库中的模型包含列:
frontend_customuser:
id
street
user_id # not sure how this is created, concat of CustomUser and User fields?
post_name
post_number
我有一个表单,使用户能够修改User
中的数据,并CustomUser
如下所示:
class BasicUserSettingsForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class CustomUserSettingsForm(forms.ModelForm):
class Meta:
model = CustomUser
fields = ['street', 'post_name', 'post_number']
views.py
我正在尝试显示/写入数据库,如下所示。我能够显示和修改User
表,但无法触摸由CustomUser
管理的(到目前为止为空的)表(我得到的错误是NOT NULL constraint failed: frontend_customuser.user_id
)。关于我可能做错了什么的任何提示?有没有一种更直接的方法通过CustomUser
写入所有这些数据(因为它仅扩展到User
)?
def settings(request):
# Prepare data to be filled into forms. User should always exist so no try/except call.
prefill_user = User.objects.get(pk=request.user.id)
# In case CustomUser table is empty, instantiate a CustomUser with request.user.id user_id.
try:
prefill_customuser = CustomUser.objects.get(pk=request.user.id)
except ObjectDoesNotExist:
prefill_customuser = CustomUser(user_id=request.user.id)
if request.method == "GET":
# If CustomUser table is empty, fields will appear empty. If prefill_customuser is successful
# at retrieving data, I expect this to be populated by values from the database.
settings_form_user = BasicUserSettingsForm(initial={'first_name': prefill_user.first_name,
'last_name': prefill_user.last_name,
'email': prefill_user.email},
instance=prefill_user)
settings_form_customuser = CustomUserSettingsForm(initial={'street': prefill_customuser.street,
'post_name': prefill_customuser.post_name,
'post_number': prefill_customuser.post_number},
instance=prefill_customuser)
if request.method == "POST":
settings_form_user = BasicUserSettingsForm(request.POST, instance=prefill_user)
try:
customuser_instance = CustomUser.objects.get(pk=request.user.id)
settings_form_customuser = CustomUserSettingsForm(request.POST, instance=customuser_instance)
except ObjectDoesNotExist:
settings_form_customuser = CustomUserSettingsForm(request.POST)
if settings_form_user.is_valid() and settings_form_customuser.is_valid():
settings_form_user.save()
settings_form_customuser.save()
else:
settings_form_user = BasicUserSettingsForm(request.POST)
settings_form_customuser = CustomUserSettingsForm(request.POST)
return render(request, 'frontend/nastavitve.html',
{'settings_form_user': settings_form_user, 'settings_form_customuser': settings_form_customuser})
创建自定义用户是创建具有OneToOne
字段到基本 Django User
模型的旧方法。在您的情况下,您需要扩展 AbstractUser
,它从 Django 1.8 开始可用:
class CustomUser(AbstractUser):
street = models.CharField(max_length=80, default="")
post_name = models.CharField(max_length=80, default=None)
并将新用户放入settings.py
:AUTH_USER_MODEL = <app_name>.CustomUser
如果要为基本用户模型添加附加字段,则此方法有效。如果你想覆盖它更复杂,你需要扩展AbstractBaseUser
起初我认为扩展User
类将是最优雅的解决方案,但我可能没有做正确的事情。现在,我选择了一个单独的表,该表有一个链接到User
表的ForeignKey
。下面描述的实现现在采用输入到表单中的值,记录/更新数据库中的表,并在表单中提供最新数据。
# --models.py
class UserAddress(models.Model):
id = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
street = models.CharField(max_length=80, default="")
# post = models.ForeignKey(PostNameNum, on_delete=models.CASCADE)
post_name = models.CharField(max_length=80, default=None)
post_number = models.IntegerField(default=None)
# --forms.py
class BasicUserSettingsForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class UserAddressSettingsForm(forms.ModelForm):
class Meta:
model = UserAddress
fields = ['street', 'post_name', 'post_number']
# --views.py
def settings(request):
# Prepare data to be filled into forms. User should always exist so no try/except call.
prefill_user = User.objects.get(pk=request.user.id)
# In case CustomUser table is empty, instantiate a CustomUser with request.user.id user_id.
try:
prefill_customuser = UserAddress.objects.get(pk=request.user.id)
except ObjectDoesNotExist:
prefill_customuser = UserAddress(id=User(id=request.user.id))
if request.method == "GET":
settings_form_user = BasicUserSettingsForm(initial={'first_name': prefill_user.first_name,
'last_name': prefill_user.last_name,
'email': prefill_user.email},
instance=prefill_user)
settings_form_customuser = UserAddressSettingsForm(initial={'street': prefill_customuser.street,
'post_name': prefill_customuser.post_name,
'post_number': prefill_customuser.post_number},
instance=prefill_customuser)
if request.method == "POST":
settings_form_user = BasicUserSettingsForm(request.POST, instance=prefill_user)
try:
settings_form_customuser = UserAddressSettingsForm(request.POST, instance=prefill_customuser)
except ObjectDoesNotExist:
settings_form_customuser = UserAddressSettingsForm(request.POST)
# if settings_form_user.is_valid() and settings_form_customuser.is_valid():
if settings_form_customuser.is_valid():
settings_form_user.save()
settings_form_customuser.save()
else:
settings_form_user = BasicUserSettingsForm(request.POST)
settings_form_customuser = UserAddressSettingsForm(request.POST)
return render(request, 'frontend/nastavitve.html',
{'settings_form_user': settings_form_user,
'settings_form_customuser': settings_form_customuser}
)