11

バナナ用の FieldList オブジェクトを 1 つ持つ果物フォームがあります。

bananas = FieldList(FormField(BananaForm))

フロントエンドでは、最初に、これらのフィールドの 1 つを FieldList に追加します。

form.append_entry()

Javascriptを使用して、情報を入力できるBananaFormフィールドの数を動的に追加(プラスボタン)または削除(マイナスボタン)できる関数を作成できました。

FielstList は、そのすべてのフィールドの ID を自動的に作成します。js で動的追加を行うには、HTML コードを複製し、フィールド id += 1 を次のように設定します。

最初のフィールド:

<tr>
  <td><input id="bananas-0-originCountry" type="text" /></td>
</tr>

+= 1 の重複フィールド:

<tr>
  <td><input id="bananas-1-originCountry" type="text" /></td>
</tr>

このように名前を付けてフォームを送信すると、WTForms はバックエンドで追加されたフィールドを自動的に認識します (正常に動作します)。

ここまでは順調ですが、ここに問題があります。フォームを有効にするには、すべての WTForm に CSRF フィールドを追加する必要があります。Jinja テンプレートでは、次のようにします。

{{ form.hidden_tag() }}

ただし、js 関数を使用して HTML をコピーするだけでは、CSRF フィールドがありません (送信されるまで、バックエンド フォーム オブジェクトは追加された FormFields を認識しないため)。では、これらの CSRF フィールドを動的に生成するにはどうすればよいでしょうか? (Ajax リクエスト? はいの場合、どのように?)

これは、フォームとフラスコの標準的な使用例です。私の説明が理解できたことを願っています。理解できない場合はお知らせください。どんな助けでも大歓迎です!

更新:これが私のコードです

JS 関数

function addBanana(){
    // clone and insert banana node
    var node = document.getElementById("fruitTable");
    var trs = node.getElementsByTagName("tr");
    var tr = trs[trs.length-2];
    var tr2 = tr.cloneNode(true);
    tr.parentNode.insertBefore(tr2, tr);

    // in order to increment label and input field ids
    function plusone(str){
        return str.replace(
            new RegExp("-(\\d+)-", "gi"),
            function($0, $1){
                var i = parseInt($1) + 1;
                return "-" + i + "-";
            }
        );
    }

    // change inputs
    var inputs = tr.getElementsByTagName("input");

    for (var i = 0; i < inputs.length; i++){
        inputs[i].setAttribute("id", plusone(inputs[i].getAttribute("id")));
    }

    var minusbutton = 
        ['<td>',
        '<button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>',
        '</td>'
        ].join('\n');

    // only append at the first add
    // second add automatically copies minus button
    if (trs.length < 6){
        tr.innerHTML += minusbutton
    }
}

function removeBanana(){
    var node = document.getElementById("fruitTable");
    var trs = node.getElementsByTagName("tr");
    var tr = trs[trs.length-2];
    var trParent = tr.parentNode;
    trParent.removeChild(tr);
}

ジンジャ テンプレート:

<form method="POST" action="newsubmit">
  {{ form.hidden_tag() }}
  <table id="fruitTable" class="table">
    {{ render_field(form.description) }}
    <tr><td><h3>Bananas</h3></td></tr>
    {% set counter = 0 %}
    {% for banana in form.bananas %} 
      <tr>
        {{ banana.hidden_tag() }}
        {% set counter = counter + 1%}
        {% for field in banana if field.widget.input_type != 'hidden' %}
          {{ render_field_oneline(field) }}
        {% endfor %}
        {% if counter > 1 %} 
          <td>
            <button class="btn" type="button" onClick="removeBanana()"><i class="icon-black icon-minus"></i></button>
          </td>
        {% endif  %} 
      </tr>
    {% endfor %}
      <tr><td></td><td><button class="btn" type="button" onClick="addBanana()"><i class="icon-black icon-plus"></i></button></td></tr>
  </table>
<input class="btn btn-primary" style="margin-left:300px;"type="submit" value="Submit" />
</form>

Jinja テンプレート マクロ:

{% macro render_field_oneline(field) %}
<td>{{ field.label }}</td>
<td>{{ field(**kwargs)|safe }}
  {% if field.errors %}
  <ul class=errors>
    {% for error in field.errors %}
    <li>{{ error }}</li>
    {% endfor %}
  </ul>
  {% endif %}
</td>
{% endmacro %}

{% macro render_field(field) %}
<tr>
  {{ render_field_oneline(field) }} 
</tr>
{% endmacro %}
4

1 に答える 1

7

私はそれがどのように機能するかを発見しました:

CSRF-Tag は簡単にコピーできます。それに応じて ID を変更して増分する必要がありますが、ハッシュは同じままでかまいません。

同じ CSRF-Tag ハッシュを持つ多くのフィールドを持つことが可能だとは思いませんでしたが、実際にはそうです!

于 2012-08-19T08:34:11.700 に答える