【问题标题】:Django Form problems with UserProfileUserProfile 的 Django 表单问题
【发布时间】:2012-08-17 13:26:41
【问题描述】:

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

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”之前似乎很难修改表单。为简单起见,我不想创建自己的表单类,也不想编写自定义表单验证。有没有其他方法可以解决问题?

【问题讨论】:

标签: django forms


【解决方案1】:

您的视图可以大大简化:

@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,这样您就没有硬编码路径。

【讨论】:

  • 很好,但是要小心,在 GET 情况下,表单未初始化。您应该将form = ... 移动到第一行。
  • 谢谢老兄。我的咖啡还没喝完。
【解决方案2】:

你基本上有两种选择:

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

【讨论】:

    【解决方案3】:

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

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

    您不必手动将清理后的数据应用到配置文件,因为 ModelForm 会这样做。

    【讨论】:

      猜你喜欢
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-23
      相关资源
      最近更新 更多