Django形式逻辑的更好模式?

时间:2011-05-03 15:13:11

标签: django django-forms

因此,Django表单的视图逻辑的标准模式是:

def contact(request):
    if request.method == 'POST': # If the form has been submitted...
        form = ContactForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            # Process the data in form.cleaned_data
            # ...
            return HttpResponseRedirect('/thanks/') # Redirect after POST
    else:
        form = ContactForm() # An unbound form

    return render_to_response('contact.html', {
        'form': form,
    })

这在简单的情况下很好,但如果你的应用程序逻辑变得有点复杂,很容易陷入复杂的嵌套IF语句中。

任何人都可以分享他们自己的清洁方法,避免嵌套的IF和依赖于坠落案件的逻辑吗?

我对那些不依赖其他第三方应用的答案特别感兴趣。

5 个答案:

答案 0 :(得分:12)

其中一个基于类的视图是FormViewdocumentation)。您需要关注的两个主要方法是form_validform_invalid

from django.views.generic import FormView

from myapp.forms import MyForm

class MyView(FormView):

    template_name = 'edit_something.html'
    form_class = MyForm
    success_url = '/success/' # you should use `reverse`, but let's stay focused.

    def form_valid(self, form):
        """
        This is what's called when the form is valid.
        """

        return super(MyView, self).form_valid(form)

    def form_invalid(self, form):
        """
        This is what's called when the form is invalid.
        """

        return self.render_to_response(self.get_context_data(form=form))

或者,您可以覆盖postgetput方法,并根据每种请求处理表单。

答案 1 :(得分:3)

这是我发现的最短路法:

def contact(request):
    # if it's POST request it'll have data else it'll  be unbound
    form = ContactForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        # Process the data in form.cleaned_data
        # ...
        return HttpResponseRedirect('/thanks/') # Redirect after POST

    return render_to_response('contact.html', { 'form': form, })

当然如果您不喜欢嵌套,如果您可以尝试倒转逻辑:

def contact(request):
    template = 'contact.html'
    if request.method != 'POST': # GET return:
        return render_to_response(template, {'form': ContactForm()})

    form = ContactForm(request.POST)
    if not form.is_valid(): # FAIL return:
        return render_to_response(template, {'form': form})

    # here logic if user posted form and it's clean:

    return HttpResponseRedirect('/thanks/')

答案 2 :(得分:2)

对于复杂场景,您应该考虑覆盖验证/清理过程中涉及的表单类的各种方法。 BaseForm类定义了一个_post_clean()方法,没有任何特别意味着被覆盖的行为。正确覆盖_clean()也非常简单,如果你想在调用clean()之前做某事,你也可以这样做。

阅读django.forms的来源,可以让您更清楚地了解表单的工作方式,并根据您的需求找到合适的模式。

答案 3 :(得分:1)

到目前为止,我尝试使视图功能更清晰:

  • GET / POST的单独视图功能
  • 显然is_valid逻辑形式为prev post中的状态。
  • 覆盖模型save()方法,使form.is_valid()部分更清晰(你可以隐藏其他相关对象在一个save()内创建)
  • 将view-funcs代码的公共部分移动到separeate函数中。
  • 如果您的GET部分不是CPU或数据库密集型,您可以在上面执行此操作,如果req == POST .. 换句话说,总是这样做.. 我经常这样做:ctx ['form'] = ContactForm()在顶部..然后再次 如果req == POST,请联系ContactForm(req.POST)

BUT 的 django 1.3现在有基于类的视图..这给了一个很大的机会 使视图可扩展..使mixins ..不要一遍又一遍地写保存。
我个人想尝试一下,并尝试用类的新风格写django的东西。

答案 4 :(得分:1)

这些情况的主要复杂性来源是在同一视图函数中处理GET和POST。将每个方法的逻辑分离到自己的视图中,事情变得更加清晰。

唯一的重复是渲染表格html,但这个特殊部分对于两种情况都是简洁而有意义的(即不是样板文件),所以这是可以接受的。