如何使用装饰器阻止重复代码处理views.py中的表单?

时间:2014-02-16 13:56:02

标签: python django django-forms python-decorators

上下文

我正在python视图中处理表单。基本的东西。

def index(request):

    # Handle form.
    if request.method == 'POST':
        form = CustomForm(request.POST)
        if form.is_valid():
            # Do stuff
            return HttpResponseRedirect('/thankyou/')
    else:
        form = CustomForm()

    # Render.
    context = RequestContext(request, {
            'form':form,
        })
    return render_to_response('app/index.html', context)

这个表单显示在多个页面上,我最终在views.py中的多个函数中复制了表单处理代码,渲染了不同的模板。 (但是,表单的模板代码位于基本模板中)

那是愚蠢的,所以我试着四处寻找防止重复代码的方法。我喜欢在this Stackoverflow问题中建议使用python decorators。我还发现了python的装饰器here的一个很好的解释。

问题

我在尝试编写装饰器时遇到了麻烦。我需要在第一个if语句之后返回一个表单,然后执行另一个if语句。但是在python函数中,return函数执行后没有代码......这是否需要像嵌套装饰器这样的东西..?

连连呢?非装饰建议欢迎。

1 个答案:

答案 0 :(得分:2)

这不是您主要问题的答案,但此信息可能对您或某人有所帮助。

关于装饰器的建议的问题已经很久了。从1.3版开始django有class based views - 我认为这就是你要找的东西。通过子类化视图,您可以减少代码重复(例如,来自django docs的代码):

# Base view
class MyFormView(View):
    form_class = MyForm
    initial = {'key': 'value'}
    template_name = 'form_template.html'

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            # <process form cleaned data>
            return HttpResponseRedirect('/success/')

        return render(request, self.template_name, {'form': form})

现在,您可以基于MyFormView视图创建另一个视图类。表单处理代码保持不变,但您当然可以更改它:

class AnotherView(MyFormView):
    form_class = AnotherForm
    initial = {'key1': 'value1'}
    template_name = 'form1_template.html'

    # you dont need to redefine post here if code stays same,
    # post from base class will be used