【问题标题】:How to populate two models using single Form如何使用单个表单填充两个模型
【发布时间】:2016-04-21 09:48:33
【问题描述】:
  class CustomAccount(models.Model):
        user = models.OneToOneField("auth.User")
        role =  models.CharField(max_length = 50,   default = 'student',    choices=APPROVAL_CHOICES)
        balance = models.FloatField( default = 0 )
        timezone = models.CharField(max_length = 200)
        def __str__(self):

            return self.user.username +" ["+ self.role + "]"

    class CustomAccountForm(forms.ModelForm):
        username = forms.CharField(max_length=30 )
        email = forms.EmailField(max_length=255 )
        password1 = forms.CharField(label= "Password",widget=forms.PasswordInput())
        password2 = forms.CharField(label="Password confirmation", widget=forms.PasswordInput , help_text="Enter the same password as above, for verification.")    

        def save(self, commit= True):
            user = User.objects.create_user(username = self.cleaned_data['username'], email = self.cleaned_data['email'] , password = self.cleaned_data['password1'])
            user.save()
            self.user = user
            return super(CustomAccountForm, self).save(commit=commit)

        def clean_username(self):
            username = self.cleaned_data["username"]
            try:
                User.objects.get(username=username)
            except User.DoesNotExist:
                return username
            raise forms.ValidationError("A user with that username already exists.")

        def clean_password2(self):
            password1 = self.cleaned_data.get("password1", "")
            password2 = self.cleaned_data["password2"]
            if password1 != password2:
                raise forms.ValidationError("The two password fields didn't match.")
            return password2
        def clean_email(self):
            email = self.cleaned_data["email"]
            try:
                User.objects.get(email=email)
            except User.DoesNotExist:
                return email
            raise forms.ValidationError("A user with that emailaddress already exists.")    
        class Meta:
            model = CustomAccount       
            exclude = ['balance','user']

我想在 Django Admin 部分使用具有 auth.User 和 CustomAccount 模型字段的单一表单创建自定义帐户。我在 /admin/mylogin/customaccount/add/ 收到错误 IntegrityError NOT NULL 约束失败:mylogin_customaccount.user_id

【问题讨论】:

  • 您在该客户帐户表中是否有预先填充的数据?
  • 是的,我有两个对象
  • 如果用户是外键,我可能会建议您在用户字段中添加null=True。当您将 OnetoOne 字段连接到用户时,您无法应用 null=True,我建议您删除 DB 中的两条记录并尝试应用迁移
  • 解决问题的最佳方法是定义自己的用户模型 - docs.djangoproject.com/en/1.9/topics/auth/customizing/…

标签: django forms python-2.7


【解决方案1】:

由于您收到非空错误,我认为您需要指定该字段不是必需的。这是我的一个应用程序中的一个示例。这表示表单字段不是必需的。

class arunModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        myuser = kwargs.pop('user', None)
        super(arunModelForm, self).__init__(*args, **kwargs)

        self.fields['nanoadded'].required = False
        self.fields['response'].required = False

我还将它包含在我的模型中,以便我的模型字段可以为空,如下所示:

class arun(models.Model):
    auser = models.CharField(max_length=50, null=True)
    adate = models.DateField(null=True)
    atime = models.TimeField(null=True)

如果我在完成这两项操作后仍然收到非空错误,我会在该字段中填写一个占位符值,以便我进一步调查问题。

【讨论】:

  • 你所说的只有当它是一个 FK 时才是正确的,你不能有 null=True 到 OnetoOne 字段
【解决方案2】:

您已经从表单中删除了用户,并且在 save 方法中,您在 save 方法中分配了 self.user。所以保存表单时,CustomAccountForm 不使用 user 属性,CustomAccount 的 user 字段为 None。

您的保存方法应如下所示:

def save(self, commit= True):
    user = User.objects.create_user(username =self.cleaned_data['username'], email = self.cleaned_data['email'] ,     password = self.cleaned_data['password1'])
    user.save()
    obj = super(CustomAccountForm, self).save(commit=False)
    obj.user = user
    obj.save()

【讨论】:

  • 现在我得到 UNIQUE 约束失败:mylogin_customaccount.user_id 错误
  • 这意味着您正在使用同一用户创建多个 CustomAccount 对象。
  • 这怎么可能我在每次保存之前创建新用户
  • 刚刚尝试了上面的代码,自己更改了保存方法。有用。您是否有可能在代码的其他部分使用相同的 user_id ? user_id 上的 UNIQUE 约束仅表示您正在尝试使用同一用户创建 CustomAccount。上面的代码没有问题,因为它每次都在创建新用户。它可能来自您代码的其他部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 2019-01-29
相关资源
最近更新 更多