我想创建一个“更新用户的个人资料”页面,让用户修改他们的个人资料,所以我想出了以下模型:
class Profile(models.Model):
user = models.OneToOneField(User)
nick_name = models.CharField(blank=True,max_length=100)
school = models.CharField(blank=True,max_length=100)
motto = models.CharField(blank=True,max_length=100)
class ProfileForm(ModelForm):
class Meta:
model = Profile
我的观点设计为:
@login_required
def update_profile_view(request):
if request.method == 'POST':
user = request.user
try:
profile = user.get_profile()
except Exception:
profile = Profile.objects.create(user=user)
form = ProfileForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
profile.nick_name = cd['nick_name']
profile.school = cd['school']
profile.motto = cd['motto']
profile.save()
return HttpResponseRedirect('/main_page/')
else:
form = ProfileForm()
return render(request, 'update_profile.html', {'form':form})
用户和个人资料之间的关系显然是1到1,并且根据请求我可以确定当前用户。因此不需要填写表单的用户字段。不幸的是,这无法通过“form.is_valid()”测试。并且在调用“is_valid”之前修改表单似乎很难。为简单起见,我不想创建自己的表单类,也不想编写自定义表单验证。有没有其他方法可以解决这个问题?
答案 0 :(得分:3)
您的观点可以大大简化:
@login_required
def update_profile_view(request):
try:
profile = Profile.objects.get(user=request.user)
except Profile.DoesNotExist:
profile = None
form = ProfileForm(request.POST or None, instance=profile)
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponseRedirect('/main_page/')
return render(request, 'update_profile.html', {'form':form})
无需像您一样手动分配字段。 Django ORM知道如何自动执行插入与更新。因此,如果您只是将ProfileForm的一个实例传递给ProfileForm,它就知道要进行更新。如果没有配置文件的实例,它将进行插入。
现在,如果您想在UI中对用户进行透明分配,则需要从表单中排除user
字段并自行分配。有几种不同的方法可以做到这一点。
我还建议您在重定向中使用reverse
,这样您就没有硬编码路径。
答案 1 :(得分:3)
您基本上有两种选择:
1 ProfileForm的修改:
class ProfileForm(ModelForm):
class Meta:
model = Profileclass
exclude = ('user',)
2更改以下行:
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
updated_profile = form.save()
答案 2 :(得分:0)
您可以将用户字段的值设置为表单的init方法中不需要的值(self.fields ['user'] .require = False),或者将用户设置为不可编辑的模型(editable = False)。
在view方法中,调用profile = form.save(commit = False),然后执行profile.user = your_user和profile.save()
由于ModelForm会执行此操作,因此您无需手动将已清理的数据应用于配置文件。