2

我想创建一个“更新用户的个人资料”页面让用户修改他们的个人资料,所以我想出了以下模型:

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

用户和个人资料之间的关系显然是 1to1,通过请求我可以确定当前用户。所以表单的用户字段不需要填写。不幸的是,这无法通过“form.is_valid()”测试。在调用“is_valid”之前似乎很难修改表单。为简单起见,我不想创建自己的表单类,也不想编写自定义表单验证。有没有其他方法可以解决问题?

4

3 回答 3

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 传递给 Profile 的一个实例,它就会知道要进行更新。如果没有配置文件的实例,它将执行插入。

现在,如果您想让用户的分配在 UI 中透明,您需要user从表单中排除该字段并自行分配。有几种不同的方法可以做到这一点。

我还建议reverse在您的重定向中利用,这样您就没有硬编码的路径。

于 2012-08-17T13:36:52.043 回答
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()
于 2012-08-17T13:39:04.870 回答
0

您可以在表单的 init 方法 (self.fields['user'].required = False) 中将用户字段的值设置为不需要,或者在模型中设置用户不可编辑 (editable=False)。

在您的视图方法中,调用 profile = form.save(commit=False),然后执行 profile.user = your_user 和 profile.save()

您不必手动将清理后的数据应用到配置文件,因为 ModelForm 会执行此操作。

于 2012-08-17T13:35:33.920 回答