在一个Django CBV中保存用户表单和资料

1 投票
2 回答
686 浏览
提问于 2025-04-18 09:28

我正在尝试在一个基于类的视图中保存两个表单。这两个表单分别是经典的用户表单和个人资料表单,其中个人资料的用户属性通过 user = models.OneToOneField() 指向用户模型。

views.py 文件中:

class ProfileEdit(LoginRequiredMixin, FormView):
    template_name = 'profiles/profile_form.html'
    success_url = reverse_lazy('profile_edit')

    def get_context_data(self, **kwargs):
        context = super(ProfileEdit, self).get_context_data(**kwargs)
        user = self.request.user
        profile = Profile.objects.get(user=user)
        user_form = UserForm(instance=user)
        profile_form = ProfileForm(instance=profile)
        context['forms'] = [user_form, profile_form]
        return context

    def post(self, request, *args, **kwargs):
        user = self.request.user
        profile = Profile.objects.get(user=user)
        user_form = UserForm(request.POST, instance=user)
        profile_form = ProfileForm(request.POST, instance=profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            messages.success(self.request, "Your profile was updated.")
            return redirect(reverse('profile_edit'))
        else:
            return super(ProfileEdit, self).get(request, *args, **kwargs)

在基本的获取请求中,我得到了

'NoneType' object is not callable

这是因为我没有提供 form_class,但我不想声明 form_class,因为我有两个表单。我在 post 方法中声明这些表单。我应该继承 FormView 还是有更好的选择呢?

另外,get_context_data 是实例化表单的合适地方吗?

2 个回答

0

这里有几种选择,但我建议你使用一个简单的TemplateView或者类似的东西。

在获取数据和提交数据时,用合适的参数来创建表单。

    def get(...):
        self.user_form = UserForm(instance=user)
        self.profile_form = ProfileForm(instance=profile)
        return super().get(...)

    def post(...)
        self.user_form = UserForm(request.POST, instance=user)
        self.profile_form = ProfileForm(request.POST, instance=profile)
        if valid:
          save_stuff()
          return redirect()
        return render_to_response(...) or super().get(...)

    def get_context_data(self, **kwargs):
        context = super(ProfileEdit, self).get_context_data(**kwargs)
        context['forms'] = [self.user_form, self.profile_form]
        return context

这样的话,get_context_data就不会处理获取或提交数据的逻辑了。

2

你可以把这两种形式合在一起使用:

class UserForm(forms.ModelForm):
    class Meta:
        model = User


class UserProfileForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        # magic 
        self.user = kwargs['instance'].user
        user_kwargs = kwargs.copy()
        user_kwargs['instance'] = self.user
        self.user_form = UserForm(*args, **user_kwargs)
        # magic end 

        super(UserProfileForm, self).__init__(*args, **kwargs)

        self.fields.update(self.user_form.fields)
        self.initial.update(self.user_form.initial)

    def save(self, *args, **kwargs):
        self.user_form.save(*args, **kwargs)
        return super(ProfileForm, self).save(*args, **kwargs)

    class Meta:
        model = UserProfile

撰写回答