3

ビュー クラスを持つページ テンプレートがあります。ページテンプレートには、同じページに送信するボタンがあります。

<form method="post" tal:attributes="action request/getURL" >
    <input type="hidden" name="filename" value="" tal:attributes="value python:item['filename']" />
    <input type="submit" name="form.action.convert" value="Convert" /> 
</form>

フォームが送信されると、ビュー クラスが呼び出されます。

class Html(BrowserView):

    def __init__(self, context, request): 
        self.request = request
        self.context = context         

    def __call__(self):
        # Is this a form submission via POST?
        req = self.request
        if req.get('REQUEST_METHOD', 'POST') and \
            req.form.get('form.action.convert', '') == 'Convert': 

            self.convert_document(self.context, str(req.form.get('filename', '')))


    def convert_document(self, contextObj, fileToConvert):
       """ Do something """
       return None

__init__ここでの問題は、このメソッドが複数回呼び出され、1 回のクリックで複数のフォームが送信されるため、メソッドにロジックを配置できないことです。ただし、__call__ボタンをクリックするとメソッドが 1 回呼び出されますが、残念ながら、リンクをクリックして現在のコンテンツ アイテムをビューに表示しても、__call__メソッドが呼び出されても何も起こらないため、何も起こりません。

__call__メソッドで以下のコードを使用できません。ブラウザーは、ページが決して終わらない方法でリダイレクトされていると文句を言います。

self.context.REQUEST.response.redirect( self.context.absolute_url() )

Ploneのページテンプレートでフォーム送信を処理するより良い方法はありますか? convert_documentページ テンプレートからビュー クラスのメソッド (つまり ) を呼び出すにはどうすればよいですか?

4

1 に答える 1

6

まず、コードに関するいくつかのコメントです。簡略化して改善することができます。

ベスト プラクティスは、フォームabsolute_url()でビューのメソッドを使用することです。これは正規の URLrequest/getURLですが、ビューが別の場所に含まれていた場合は、奇妙な獲得や間違った URL が含まれている可能性があります。

<form method="post" tal:attributes="action view/absolute_url" >
    <input type="hidden" name="filename" value="" tal:attributes="value item/filename" />
    <input type="submit" name="form.action.convert" value="Convert" /> 
</form>

入力ボックスの tal 式では、パス式を使用できます。filenameこれらは辞書で問題なく機能します。

__init__メソッドを再定義する必要はありませんBrowserView。クラスはすでにそれを提供しています。

フォームが送信されたかどうかをテストするには、通常、リクエストに送信ボタンが存在するかどうかをテストするだけです。テストは必要以上に複雑です。

def __call__(self):
    if 'form.action.convert' in self.request.form: 
        self.convert_document()

はビューのメソッドであるため、それ自体がおよびにconvert_documentアクセスでき、メソッド シグネチャが簡素化されます。フォームが送信されたことがわかったので、存在して文字列であると期待できます。誰かが手動でリクエストをいじっていて、物事が壊れるに値しない場合、私は通常、そのような場合には使用しません。self.contextself.request.form['filename']self.request.form['filename']get(..., '')

ビューは常に__call__メソッド内ですべての作業を行う必要があり__init__ます。これは、トラバーサル中に が呼び出され、その時点では現在のユーザーなどの重要な情報がまだ決定されていないためです。redirectコンテキストを介してメソッドの応答にアクセスする必要はありません。self.request属性からアクセスするだけですが、結果を返すことを忘れないでください。

return self.request.response.redirect(self.context.absolute_url())

ただし、ビューがコンテキスト オブジェクトのデフォルトのビューである場合、ブラウザが許容できないリダイレクト ループが実際に発生します。

__call__テンプレートが関連付けられているビュー クラスのメソッドをオーバーライドする場合はBrowserView、必要に応じてテンプレートの出力を返すようにする必要があります。したがって、ビュークラスでの私の刺し傷は次のようになります。

class Html(BrowserView):
    def __call__(self):
        if 'form.action.convert' in self.request:
            self.convert_document()
            return self.request.response.redirect(self.context.absolute_url())
        return self.index()

    def convert_document(self):
       """ Do something """
       context = self.context
       filename = self.request.form['filename']
       # Do something with the context and filename
于 2012-10-16T09:07:18.943 に答える