request.form値をurl_forに渡すFlask

ラファタック

私はページを表示フラスコテンプレート持つdropdownのリストをownerstable所有者の勝敗記録を持つ、とradio切り替えるにはregularシーズン記録とplayoff記録。

必要なワークフローは次のとおりです。

  1. ナビゲーションバーからページに移動した場合、デフォルトで/matchup-history/regularになります(これは動作します)
  2. それ以外の場合は、radioが切り替えられるたびにそれに応じてルーティングする必要があります。(これは機能しません)

matchup-history.html

{%- extends "base.html" -%}
{% block nav_matchups %}active{% endblock %}
{%- block content -%}
  <form action="{{ url_for('show_matchup_history', matchup_type=request.form['matchup_type']) }}" method="post">
    <label>
      <select name="owner_id" onchange="this.form.submit()">
      {%- for o in owners %}
        {%- if request.form['owner_id'] == o['owner_id']|string() %}
        <option value="{{ o['owner_id'] }}" selected>{{o['first_name'] + " " + o['last_name'] }}</option>
        {%- else %}
        <option value="{{ o['owner_id'] }}">{{o['first_name'] + " " + o['last_name'] }}</option>
        {%- endif %}
      {%- endfor %}
      </select>
    </label>
    {% block matchup_type_radio %}{% endblock %}
  </form>
  {%- if records|length > 0 %}
  <div class="stats-table">
    <table>
      <tr>
        {%- for th in table_headers %}
        <th>{{ th }}</th>
        {%- endfor %}
      </tr>
      {%- for r in records %}
      <tr>
        {%- for cn in column_names %}
        <td>{{ r[cn] }}</td>
        {%- endfor %}
      </tr>
      {%- endfor %}
    </table>
  </div>
  {%- endif %}
{% endblock -%}

matchup-history / regular.html

{%- extends "matchup-history.html" -%}
{% block matchup_type_radio %}
<label><input type="radio" name="matchup_type" value="regular" onclick="this.form.submit()" checked>Regular Season</label>
<label><input type="radio" name="matchup_type" value="playoffs" onclick="this.form.submit()">Playoffs</label>
{% endblock %}

matchup-history / playoffs.html

{%- extends "matchup-history.html" -%}
{% block matchup_type_radio %}
<label><input type="radio" name="matchup_type" value="regular" onclick="this.form.submit()">Regular Season</label>
<label><input type="radio" name="matchup_type" value="playoffs" onclick="this.form.submit()" checked>Playoffs</label>
{% endblock %}

app.py

@app.route('/matchup-history/<string:matchup_type>', methods=['GET', 'POST'])
def show_matchup_history(matchup_type):
    table_headers = ["Opponent", "Wins", "Losses"]
    column_names = ["opponent_owner_name", "wins", "losses"]
    owners = queries.get_owners()

    if request.method == 'POST':
        owner_id = request.form['owner_id']
    else:
        owner_id = owners[0]['owner_id']

    if matchup_type == REGULAR_SEASON:
        records = queries.get_matchup_history_regular(owner_id)
    else:
        records = queries.get_matchup_history_playoffs(owner_id)

    return render_template("matchup-history/{matchup_type}.html".format(matchup_type=matchup_type),
                           title='Matchup History', table_headers=table_headers, column_names=column_names,
                           owners=owners, records=records)

/matchup-history/regularクリックするとページは正しく読み込まれますが、ラジオボタンを切り替えると失敗します。

127.0.0.1 - - [20/Sep/2018 08:32:53] "GET /matchup-history/regular HTTP/1.1" 200 -
127.0.0.1 - - [20/Sep/2018 08:32:56] "POST /matchup-history/ HTTP/1.1" 404 -

レンダリングするrequest.form['matchup_type']と空のように見えるmatchup-history.htmlため、フォームを送信しても期待した効果は得られません。url_for別のルートにリファクタリングするにはどうすればよいmatchup_typeですか?

編集:パー@Joostさんの提案、私はデザインを再考します。

matchup-history.html

{%- extends "base.html" -%}
{% block nav_matchups %}active{% endblock %}
{%- block content -%}
  <form action="{{ url_for('show_matchup_history') }}" method="get">
    <label>
      <select name="owner_id" onchange="this.form.submit()">
      {%- for o in owners %}
        <option value="{{ o['owner_id'] }}" {%- if o['owner_id'] == selected_owner %} selected {% endif %}>{{o['first_name'] + " " + o['last_name'] }}</option>
      {%- endfor %}
      </select>
    </label>
    <label><input type="radio" name="matchup_type" value="regular" onclick="this.form.submit()" {%- if matchup_type == "regular" %} checked {% endif %}>Regular Season</label>
    <label><input type="radio" name="matchup_type" value="playoffs" onclick="this.form.submit()"{%- if matchup_type == "playoffs" %} checked {% endif %}>Playoffs</label>
  </form>
  {%- if records|length > 0 %}
  <div class="stats-table">
    <table>
      <tr>
        {%- for th in table_headers %}
        <th>{{ th }}</th>
        {%- endfor %}
      </tr>
      {%- for r in records %}
      <tr>
        {%- for cn in column_names %}
        <td>{{ r[cn] }}</td>
        {%- endfor %}
      </tr>
      {%- endfor %}
    </table>
  </div>
  {%- endif %}
{% endblock -%}

base.html

...
<a href="{{ url_for('show_matchup_history') }}" class="{% block nav_matchups %}{% endblock %}">Matchups</a>
...

app.py

@app.route('/matchup-history', methods=['GET'])
def show_matchup_history():
    table_headers = ["Opponent", "Wins", "Losses"]
    column_names = ["opponent_owner_name", "wins", "losses"]

    matchup_type = request.args.get('matchup_type', default="regular")
    owner_id = request.args.get('owner_id', type=int)
    owners = queries.get_owners()

    if not owner_id:
        owner_id = owners[0]['owner_id']

    if matchup_type == REGULAR_SEASON:
        records = queries.get_matchup_history_regular(owner_id)
    else:
        records = queries.get_matchup_history_playoffs(owner_id)

    return render_template("matchup-history.html".format(matchup_type=matchup_type),
                           title='Matchup History', table_headers=table_headers, column_names=column_names,
                           matchup_type=matchup_type, selected_owner=owner_id, owners=owners, records=records)

フローは次のとおりです。

  1. Matchupsナビゲーションバーからクリックすると、/matchup-history通常のシーズンの対戦にルーティングされ、デフォルトで表示されます
  2. Playoffsラジオをクリックすると、にルーティングされます/matchup-history?matchup_type=playoffs&owner_id=12345
  3. Regularラジオをクリックすると、にルーティングされます/matchup-history?matchup_type=regular&owner_id=12345
  4. 中に別の所有者をクリックするdropdown意志ルートへ/matchup-history?matchup_type=regular&owner_id=98765
Joost

そのため、現在request.form、getリクエストでにアクセスしようとしていますただし、これformはgetリクエストの性質であるため、getリクエストでは常に空になります。したがって@app.route('/matchup-history/<string:matchup_type>'、POSTリクエストを介してルートにアクセスした場合にのみ、正しい方法でリダイレクトできます。

この動作するミニアプリはそれをうまく表示します:

from flask import Flask, render_template_string, request
app = Flask(__name__)

TEMPLATE_STRING = """
    <form action="{{ url_for('index') }}" method="post">
    {{request.form['matchup_type']}}<br><br>
    <label><input type="radio" name="matchup_type" value="regular" onclick="this.form.submit()" checked>Regular Season</label>
    <label><input type="radio" name="matchup_type" value="playoffs" onclick="this.form.submit()">Playoffs</label>
    </form>
"""


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template_string(TEMPLATE_STRING)
    else:
        return render_template_string(TEMPLATE_STRING)

初めてページを開くと、ラジオボタンのみが表示されます。ただし、ラジオボタンをクリックするとすぐにフォームが送信されるため、選択した値がページの上部に表示されます。もう一度クリックすると、フォームをもう一度投稿します。

では、どのように解決すればよいのでしょうか。データを更新しておらず、クエリを実行しているだけなので、このフォームでPOSTリクエストを実行する必要はないと思います。

    from flask import Flask, render_template_string, request
app = Flask(__name__)

TEMPLATE_STRING = """
    <form action="{{ url_for('history') }}" method="get">
    <select name="owner_id">
    {% for owner in owners %}
      <option {% if owner['id'] == selected_owner_id %} selected {% endif %}value="{{owner['id']}}">{{owner['name']}}</option>
     {% endfor %}
    </select>
    <label><input type="radio" name="matchup_type" value="regular" {%if selected_matchup_type == 'regular'%}checked{%endif%} onclick="this.form.submit()">Regular Season</label>
    <label><input type="radio" name="matchup_type" value="playoffs" {%if selected_matchup_type == 'playoffs'%}checked{%endif%} onclick="this.form.submit()"  >Playoffs</label>
    <br>Queried data goes here
    </form>
"""
owners = [{'id': 1, 'name': 'bob'}, {'id': 2, 'name': 'gary'}, {'id': 3, 'name': 'tom'}]
matchup_types = 'regular', 'playoffs'


@app.route('/history', methods=['GET'])
def history():
    owner_id = request.args.get('owner_id', None, type=int)
    if owner_id not in [owner['id'] for owner in owners]:
        owner_id = owners[0]['id']
    matchup_type = request.args.get('matchup_type', None)
    if matchup_type not in matchup_types:
        matchup_type = matchup_types[0]
    # now you know the owner_id and the matchup type, and know that both are valid, do some query to get table data
    return render_template_string(TEMPLATE_STRING, owners=owners,
                                  selected_owner_id=owner_id,
                                  selected_matchup_type=matchup_type,
                                  matchup_types=matchup_types)

これがあなたに必要なものだと思います。フォームは投稿されることはなく、常にgetリクエスト(<form action="{{ url_for('history') }}" method="get">として配置されます。値が欠落しているか無効である場合、デフォルトでいくつかのowner / matchup_typeに戻ります。チェックされた値は記憶され、テンプレートのレンダリングに使用されます。

これにより、すべてのフラスコロジックがに配置され、@app.routeすべてのjinjaロジックがテンプレートに配置されます。

いくつかの一般的な意見:

requestjinjaはエラー/欠落値の処理方法が異なるためin jinjaにアクセスすることは好ましくないと思います。また、それらが要求に関連するロジックの結果である場合、何が起こっているのかを推測するのが難しくなります。したがって、Python側で着信要求を処理します。

選択した値に応じて2つの無線ブロックをラップする代わりに、1つのブロックを使用して、必要なものかどうかをオプション内で確認します。<option {% if some_value == some_other_value %} checked {% endif%}>blabla</option>

より多くの入力検証を行います!最初の例では、テンプレート名はユーザーが入力した値(マッチアップタイプ)によって決定されます。しかし、ユーザーが存在しない値を投稿した場合はどうなりますか?エラーが発生します。

2つのテンプレートの唯一の違いがどちらのラジオボタンが選択されているかである場合、2つのテンプレートは必要ありません。1つのテンプレートでそれを処理する方法を更新したバージョンを参照してください。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Flask-フォーム入力をurl_forに渡します

分類Dev

NullableIntをmvcのRequest.Form []に渡します

分類Dev

Get referring URL for Flask request

分類Dev

request.META in flask?

分類Dev

Request .Form returns null

分類Dev

関数search_click()に3つ以上のrequest_urlを渡す方法

分類Dev

Postman request with 'global' URL

分類Dev

clipboard fill url request

分類Dev

$ _GET for + in url get request?

分類Dev

$ _GET for + in url get request?

分類Dev

(Request $request) を使う意味は?

分類Dev

url_for()を使用してFlaskに動的URLを作成する

分類Dev

Passing URL parameter to post request form in Laravel

分類Dev

MPI_Request を値で渡しても大丈夫ですか?

分類Dev

httpsの代わりにhttp URLを生成するFlask url_for

分類Dev

Request.form はコンマで値を返します

分類Dev

未定義のrequest.bodyを渡すJavascriptAJAX

分類Dev

AWS Serverless contact form request

分類Dev

DELETE request outside of form Laravel

分類Dev

How to submit a post request to a form?

分類Dev

Incomplete Form Data in ajax request

分類Dev

js変数をflaskjinja関数url_forに渡す方法

分類Dev

Flask request.form ["name"]はトークンを1つだけ返します

分類Dev

Flaskで「 'Request'オブジェクトに属性 'Name'」を取得する

分類Dev

Hide request parameters in apex url

分類Dev

MVC 5 request domain url

分類Dev

「net / http」で* Requestを関数Golangに渡す

分類Dev

余分な引数をscrapy.Request()に渡す

分類Dev

htaccessからPHPにREQUEST_URIを渡す方法