我有一个名为Personnel
的模型,我将其用作User
模型的配置文件模型。这是我的模特
class Personnel(models.Model):
user = models.OneToOneField(
User
)
phone = models.CharField(
null=False, max_length=50, verbose_name="Phone"
)
我需要在ModelForm中使用上面的模型。这是我的ModelForm
:
class PersonnelForm(forms.ModelForm):
class Meta:
model = Personnel
exclude = ('user')
def __init__(self, *args, **kwargs):
personnel = Personnel(user=User.objects.create(username=(''.join(choice(ascii_uppercase + digits) for x in range(30)))))
super(PersonnelForm, self).__init__(
instance=personnel, *args, **kwargs
)
我不需要在网络上显示user
字段,因此我将其排除在外。但是我仍然需要为它传递一个值,所以通过传递PersonnelForm
实例来启动我的Personnel
。 User
模式有一个名为email
的字段,应由用户输入,但我无法显示此字段,因为它不是Personnel
模型上的字段。
我可以创建一个名为email
的虚拟字段,在设置时,设置user.email
字段的值,当获取时,获取相同的值。像这样:
@property
def email():
def fget(self):
return 'fff'
def fset(self, email):
self.user.email = email
我需要以某种方式与上述代码段类似,因为我将PersonnelForm
与Django's generic CRUD views一起使用。
感谢。
(请随时编辑并为标题建议一个更好的名称,以便它也可能对其他人有所帮助。)
使用丹尼尔的建议:
class PersonnelForm(forms.ModelForm):
email = forms.EmailField(
required=True, label=_("Email")
)
class Meta:
model = Personnel
exclude = ('user')
def save(self, *args, **kwargs):
commit = kwargs.get('commit', True)
kwargs['commit'] = False
personnel = super(PersonnelForm, self).save(*args, **kwargs)
if not personnel.user: #To prevent creating a new user when updating.
user = User.objects.create_user(
email=self.cleaned_data['email'],
username=(''.join(choice(ascii_uppercase + digits) for x in range(30))),
)
if commit:
personnel.save()
return personnel
这适用于使用ModelForm创建新记录,但我无法在更新时更新电子邮件或查看电子邮件。
答案 0 :(得分:1)
你的问题有两个误解。首先,即使您已将其排除,也需要为该字段传递值;其次,您不能包含不在模型上的字段。这些都不是真的。
绝对可以定义一个单独的email
字段,将其与实际模型字段一起显示在表单上,然后使用该值创建User
对象。
鉴于您不想修改视图来执行此逻辑(IMO是错误的决定,但这是您的代码),您可以使用重写的save
方法执行此操作:
class PersonnelForm(forms.ModelForm):
email = forms.CharField()
class Meta:
model = Personnel
exclude = ('user',)
def save(self, *args, **kwargs):
# call super method with commit=False, but remember original commit arg
commit = kwargs.get('commit', True)
kwargs['commit'] = False
new_object = super(PersonnelForm, self).save(*args, **kwargs)
user = User.objects.create_user(
email=self.cleaned_data['user'],
username=get_random_username(),
password=User.objects.make_random_password()
)
new_object.user = user
# now save if commit was not explicitly set to False
if commit:
new_object.save()
return new_object