如何使用ModelForm

时间:2016-07-09 17:10:05

标签: django sqlite django-forms

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

我有一个表单,可让用户修改UserCustomUser中的数据,如下所示:

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我尝试显示/写入DB,如下所示。我能够显示和修改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})

2 个答案:

答案 0 :(得分:0)

使用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
如果要为基本用户模型添加aditional字段,则此方法有效。如果您想要覆盖它更复杂,则需要退出AbstractBaseUser

答案 1 :(得分:0)

起初我认为扩展User类将是最优雅的解决方案,但是我可能没有做正确的事情。目前,我已经选择了一个单独的表,其中ForeignKey链接到User表。下面描述的实现现在将输入的值输入到表单中,在数据库中记录/更新表,并以表格形式提供最新数据。

# --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}
                  )