如何编写到使用模型窗体扩展用户的类



我有一个扩展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}
                  )

最新更新