【问题标题】:Call post function of a class based view using formview使用 formview 调用基于类的视图的 post 函数
【发布时间】:2015-03-20 16:18:56
【问题描述】:

我是基于 django 类的视图的新手,可能是我接近这个的方式有点天真,所以如果你能提出更好的方法,我将不胜感激。

所以我的问题就在这里:

我的项目中有三种类型的用户。 1. 学生,2. 老师,3. 家长。当用户以各自的表单请求设置页面时,我需要能够显示与每种类型的用户相关的不同用户设置。此外,当用户提交表单时,我需要能够将数据保存到相应的表中。

我有一个基于类的视图 (UserSettingsView):

class UserSettingsView(LoginRequiredMixin, FormView):
    success_url = '.'
    template_name = 'accts/usersettings.html'

    def get_initial(self):
        if self.request.user.is_authenticated():
            user_obj = get_user_model().objects.get(email=self.request.user.email)
            if user_obj.profile.is_student:
                return {
                    'first_name': user_obj.profile.first_name,
                    'last_name': user_obj.profile.last_name,
                    """ and other student field variables """
                    }
            if user_obj.profile.is_teacher:
                return {
                    """ Teacher field variables """
                    }
        else:
            return render_to_response('allauth/account/login.html')

    def form_valid(self, form):
        messages.add_message(self.request, messages.SUCCESS, 'Settings Saved!')
        return super(UserSettingsView, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(UserSettingsView, self).get_context_data(**kwargs)
        context['user'] = get_user_model().objects.get(email=self.request.user.email)
        context['userprofile'] = UserProfile.objects.get(user_id=context['user'])
        return context

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        form.full_clean()

        if form.is_valid():
            user = request.user
            user.profile.first_name = form.cleaned_data['first_name']
            user.profile.last_name = form.cleaned_data['last_name']
            user.profile.save()
            if user.profile.is_student:
            """ update student database """
                user.save()
                user.student.save()
            if user.profile.is_teacher:
            """ update teacher database """
                user.save()
                user.teacher.save()

            return self.form_valid(form)
        else:
            return self.form_invalid(form)

使用 pick_settings 通用视图调用不同的 Usersettings 视图实例。

url(regex=r'^profilesettings/',view=pick_settings,name='profilesettings'),

这里是 pick_settings 视图:

def pick_settings(request):
    if request.user.is_authenticated():
        if request.method == 'GET':
            if request.user.profile.is_student:
                return UserSettingsView.as_view(form_class=StudentSettingsForm)(request)
            if request.user.profile.is_teacher:
                return UserSettingsView.as_view(form_class=TeacherSettingsForm)(request)
            if request.user.profile.is_parent:
                return UserSettingsView.as_view(form_class=ParentSettingsForm)(request)
        else:
            if request.method == 'POST':
                """
         return ***<--- I need to know what to pass here to be able to call the appropriate post function of the UserSettingsView?---->"""***
    else:
            return HttpResponseRedirect('/accounts/login/')

我需要能够调用 UserSettingsView 的 post 函数。可能正在使用 get_context_data?但我不确定如何。

如果有人能提出更好的方法,那就太好了,因为我很确定这可能违反了 DRY 原则。不过,只要我在截止日期前完成工作,我就不会太担心这一点。 :) 谢谢!

【问题讨论】:

    标签: django django-class-based-views formview


    【解决方案1】:

    FormView 有一个方法get_form_class()。它是从get()post() 调用的,所以self.request 已经被设置(self.request.user 也是如此)。因此,

    class UserSettingsView(LoginRequiredMixin, FormView):
       [...]
       def get_form_class(self):
           # no need to check is_authenticated() as we have LoginRequiredMixin
           if request.user.profile.is_student:
                return StudentSettingsForm
           elif user.profile.is_teacher:
                return TeacherSettingsForm
           elif user.profile.is_parent:
                return ParentSettingsForm
    

    当您为每种用户类型获得正确的表单时,这应该已经成功了。

    如果你还需要渲染不同的模板,覆盖get_template_names():

       def get_template_names(self):
           if request.user.profile.is_student:
                return ['myapp/settings/student.html']
           elif user.profile.is_teacher:
                return ['myapp/settings/teacher.html']
           elif user.profile.is_parent:
                return ['myapp/settings/parent.html']
    

    可以在模板中使用适当的继承来实现 DRY,并结合常见的模板片段。

    以免我忘记(我已经忘记了):为了摆脱你视图的 post() 方法中的 if,简单地覆盖你的表单的 save() 方法,我假设它是 ModelForms,无论如何。

    【讨论】:

    • 感谢您的及时回复。这很棒。我低估了 FormView 的实力,因为它能够使用 self.request.user 选择相应的用户设置表单,这就是我编写单独的 sn-p 来选择表单的原因。过度使用保存功能有点棘手,因为我在家长/老师和学生档案之间建立了条件联系。无论如何,我希望这对其他人也有帮助。
    • 无论如何这都不是坏代码。我唯一想做的就是将保存直接移动到form_valid()。这不会从get() 调用,并且更容易从其他地方调用。
    猜你喜欢
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多