我认为我的问题非常明显,几乎每个使用 UserProfile
的开发人员都应该能够回答它。
然而,我在 Django 文档或《Django Book》中找不到任何帮助。
当您想要在 Django Forms 中创建一个 UserProfile
表单时,您希望修改配置文件字段以及某些 User
字段。
但是,目前还没有 forms.UserProfileForm
(还没有吗?)!
那么,如何实现呢?
我认为我的问题非常明显,几乎每个使用 UserProfile
的开发人员都应该能够回答它。
然而,我在 Django 文档或《Django Book》中找不到任何帮助。
当您想要在 Django Forms 中创建一个 UserProfile
表单时,您希望修改配置文件字段以及某些 User
字段。
但是,目前还没有 forms.UserProfileForm
(还没有吗?)!
那么,如何实现呢?
我今天偶然发现了这个问题,经过一些搜索,我找到了一个在我看来更加简洁的解决方案:
#in forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ["username", "email"]
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
#in views.py
def add_user(request):
...
if request.method == "POST":
uform = UserForm(data = request.POST)
pform = UserProfileForm(data = request.POST)
if uform.is_valid() and pform.is_valid():
user = uform.save()
profile = pform.save(commit = False)
profile.user = user
profile.save()
....
...
#in template
<form method="post">
{{ uform.as_p }}
{{ pform.as_p }}
<input type="submit" ...>
</form>
这是我最终的做法:
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(label=_(u'Prénom'), max_length=30)
last_name = forms.CharField(label=_(u'Nom'), max_length=30)
def __init__(self, *args, **kw):
super(UserProfileForm, self).__init__(*args, **kw)
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields.keyOrder = [
'first_name',
'last_name',
...some_other...
]
def save(self, *args, **kw):
super(UserProfileForm, self).save(*args, **kw)
self.instance.user.first_name = self.cleaned_data.get('first_name')
self.instance.user.last_name = self.cleaned_data.get('last_name')
self.instance.user.save()
class Meta:
model = UserProfile
User
模型上使用post_save
信号,就不会出现这种情况。详情请参见:http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users。 - Natimadmin.py
中:class ProfileAdmin(admin.ModelAdmin):
form = ProfileForm
def save_model(self, request, obj, form, change):
obj.user.first_name = form.cleaned_data['first_name']
obj.user.last_name = form.cleaned_data['last_name']
obj.user.save()
obj.save()
forms.py
文件中:class ProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=256)
last_name = forms.CharField(max_length=256)
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
try:
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
except User.DoesNotExist:
pass
class Meta:
fields = ['first_name', 'last_name', ...etc.]
obj.save()
保存配置文件。你是正确的,它只在管理界面中起作用。我不得不将其构建到其中。要使其在应用程序视图中起作用,您应该将逻辑从管理界面移动到表单中。就像你在save
方法中所做的那样。 - wunkiclass SignUpForm(forms.ModelForm):
first_name = forms.CharField(max_length = 30)
last_name = forms.CharField(max_length = 30)
username = forms.CharField(max_length = 30)
password = forms.CharField(widget = forms.PasswordInput)
password1 = forms.CharField(widget = forms.PasswordInput)
class Meta:
model = UserProfile
exclude = ['user']
def clean_username(self): # check if username does not exist before
try:
User.objects.get(username=self.cleaned_data['username']) #get user from user model
except User.DoesNotExist :
return self.cleaned_data['username']
raise forms.ValidationError("This user exist already choose an0ther username")
def clean(self, *args , **kwargs):
super(SignUpForm).clean(*args ,**kwargs) # check if password 1 and password2 match each other
if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:#check if both pass first validation
if self.cleaned_data['password1'] != self.cleaned_data['password2']: # check if they match each other
raise forms.ValidationError("Passwords don't match each other")
return self.cleaned_data
def save(self): # create new user
new_user = User.objects.create_user(username=self.cleaned_data['username'],password=self.cleaned_data['password1'],email=self.cleaned_data['email'])
new_user.first_name = self.cleaned_data['first_name']
new_user.last_name = self.cleaned_data['last_name']
new_user.save()
UserProf = super(SignUpForm,self).save(commit = False)
UserProf.user = new_user
UserProf.save()
return UserProf
您也可以尝试使用django-basic-apps项目,其中包含一个profiles应用程序:
如果您将两个模型合并到一个表单中,我认为在文档中找不到任何信息是正常的。
或者,您可以很明显地创建两个模型表单,一个用于用户,另一个用于用户配置文件。将用户配置文件模型表单设置为仅显示名字和姓氏。将两个表单放在同一个模板中,在单个<form>
标记内。提交表单时,调用每个表单的保存方法。
{{form}}
。使用我提供的解决方案,您可以随心所欲地进行操作,并继续使用表单框架。 - Natim
title
字段,它应该在first_name
和last_name
之前,但仍然属于pform
。 - Natim