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

もちろん、繰り返しを避けることができます。ほとんどの場合、使用するフォームのクラスとテンプレート名、有効なフォームが送信されたときに消去されたデータを処理する呼び出し可能オブジェクト、およびそのような処理後のリダイレクトの宛先を引数として渡す必要があります。さらに、フォーム クラスを 1 回だけ呼び出して、バインドされたフォームまたはバインドされていないフォームを生成し、それを適切に処理するには、少し追加のコードが必要です。すなわち:

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 に答える
2

フォームを処理する定型的な方法には、編集するフォームを提示することと結果を処理することの 2 つの懸念事項が混在しています。これを 2 つのメソッドに分割すると、同一の render_to_response() 呼び出しの形で重複が発生します。それをリファクタリングするまでに、上記の単一メソッド形式よりも読みにくいものになる可能性があります。

ボイラープレート メソッドを見ると、重複は見られません。ContactForm() の 2 つの使用法は明確に異なります。2 つの条件は、フォームの処理に関連する状態遷移をかなり明確に示しているように思えます (空白のフォームを提示し、一方が有効になるまで送信を受け入れ、処理してリダイレクトします)。

于 2009-07-18T22:25:02.197 に答える
1

私はこれにとてもうんざりして、それを処理するために私自身の一般的な見解を書きました。その過程で、djangoにはすでにフォーム処理の一般的なビューが十分に文書化されていないことがわかりました。これらは、文書化された一般的なビューのかなり直接的な類似物ですが、フォームを受け入れ、基本的に、例で使用したものと同じテンプレートに従います。最終的には、柔軟性がなく、使用するには愚かであることがわかりました(create_or_updateビューは必要ありません。これらの2つのアクションを別々に扱いたくありません)。

編集:あなたは私が話しているのと同じことを指しているフラグスワースの答えが気に入らなかった、私はあなたも私のようには思わないだろうと思う。これがどのように機能するかの例です。

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

ContactFormメソッドが必要でありsave()、それがフォーム処理ロジックの目的です。

于 2009-07-19T00:30:48.630 に答える
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 に答える
0

djangoのフォームモジュールをバイパスして、昔ながらの方法で行うことができます。私見をあまり損なうことなく、柔軟性を高めることができます。

前回djangoフォームを見たのはかなり前のことで、状況が変わったかどうかはわかりませんが、たとえば、ajaxスタイルのフォームを作成することはできません。少なくとも簡単ではありません。

于 2009-07-19T00:36:54.530 に答える
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 に答える