7

在视图中处理表单的建议模式对我来说似乎过于复杂和非 DRY:

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,
    })

这是很多条件,它重复了 ContactForm() 构造,并且在视图需要处理表单的任何地方都重复了整个块。难道没有更好的方法吗?

4

8 回答 8

10

当然,您可以避免重复。大多数情况下,您需要将要使用的表单类和模板名称作为参数传递,在提交有效表单时处理已清理数据的可调用函数,以及在此类处理后重定向的目标;另外,您需要一些额外的代码来调用表单类一次,以生成绑定或未绑定的表单,并正确处理它。IE:

def process_any_form(request, 
                     form_class, template_file_name,
                     process_data_callable, redirect_destination):

    form = form_class(request.POST if request.method == 'POST' else None)

    if form.is_bound and form.is_valid():
        process_data_callable(form.cleaned_data)
        return HttpResponseRedirect(redirect_destination)

    return render_to_response(template_file_name, {'form': form})
于 2009-07-18T22:49:04.643 回答
6

你是对的,它可能会更好,这是一个更好的选择(但请继续阅读):

def contact(request):
     form = ContactForm(request.POST or None) # 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

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

这个片段来自DjangoCon11的一个名为Advanced Django Form Usage的演讲。

请注意,如果所有字段都是可选的并且您不使用 CSRF 保护,这将处理一个有效的空表单(甚至在提交之前)。所以为了消除这种风险,你最好使用这个:

    def contact(request):
     form = ContactForm(request.POST or None) # A form bound to the POST data
     if request.method == 'POST' and form.is_valid(): # All validation rules pass
        # Process the data in form.cleaned_data
        # ...
        return HttpResponseRedirect('/thanks/') # Redirect after POST

     return render_to_response('contact.html', {
        'form': form,
     })
于 2011-09-24T13:00:45.050 回答
2

处理表单的样板方式混合了两个问题:呈现表单以编辑和处理结果。您可以将其分解为两种方法,这会以相同的 render_to_response() 调用的形式引入一些重复。当你重构它时,你最终可能会得到比上面的单一方法形式更不可读的东西。

当我查看样板方法时,我看不到重复。ContactForm() 的两种用法明显不同。在我看来,这两个条件相当清楚地显示了处理表单所涉及的状态转换(呈现一个空白表单,接受提交直到一个有效,处理和重定向)。

于 2009-07-18T22:25:02.197 回答
1

亚历克斯的通用处理程序击败了我,但 FWIW 我们倾向于他建议的不太通用的版本:

def contact(request):
    post_data = request.POST if request.method == 'POST' else None
    form = ContactForm(post_data)
    if request.method == 'POST':
        # perform normal validation checking, etc

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

如果 post_data 为 None,则该表单被实例化为无界。否则,绑定处理照常继续。它避免了 ContactForm 的重复构造,但我同意 Dave 的回答,即由于构造参数不同,重复构造不会因为重复构造而困扰我。

于 2009-07-18T23:41:30.137 回答
1

我对此感到厌倦,以至于我编写了自己的通用视图来处理它。在这个过程中,我发现 django已经为表单处理提供了文档不足的通用视图。它们是记录的通用视图的直接类似物,但接受表单,并且基本上遵循您在示例中使用的相同模板。最终,我发现它们对于我的使用来说太不灵活和愚蠢(我不想要 create_or_update 视图,我不想单独处理这两个动作。)

编辑:您不喜欢 Fragsworth 的回答,这指向了我正在谈论的同一件事,我想您也不会喜欢我的。这是它如何工作的示例。

# in urls.py
urlpatterns += patterns("", 
    (u'^...$', 'django.views.generic.create_update.update', {
        'form_class': ContactForm })
)

ContactForm必须有一个save()方法,这就是您的表单处理逻辑所在。

于 2009-07-19T00:30:48.630 回答
0

可以编写一个函数来处理所有表单的条件。您可以通过在“is_valid”之后传入特定于该表单的函数来做到这一点,例如:

def FormHandler(request, CleaningFunction, redirecturl):
    if request.method = 'POST':
        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
                CleaningFunction(form) # Process the data in form.cleaned_data
                return HttpResponseRedirect('/thanks/') # Redirect after POST
     else:
         form = ContactForm() # An unbound form
     return form

然后你会从你的视图中调用 FormHandler 。请注意,这未经测试,可能有错误。

于 2009-07-18T22:26:41.443 回答
0

Django 提供了几个用于创建、编辑和删除对象的通用视图。也许你可以试试这些。

于 2009-07-18T22:45:12.437 回答
0

您可以绕过 django 的表单模块并以旧的方式进行操作,您可以获得更大的灵活性而不会造成太多损失,恕我直言。

上次我看 django 表单是很久以前的事了,我不知道事情是否发生了变化,但例如,它并不能真正让你构建一个 ajax 样式的表单;至少不容易。

于 2009-07-19T00:36:54.530 回答