将用户表单和配置文件保存在一个Django CBV中

时间:2014-06-11 19:21:00

标签: python django forms

我试图在一个基于类的视图中保存两个表单。表单是经典的用户表单和个人资料表单,其中Profile的用户属性指向模型中带有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 :(得分: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

答案 1 :(得分:0)

这里有一些选项,但我会使用简单的TemplateView或类似的

使用适当的参数

在get和post中实例化表单
    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将不处理get或post

的逻辑