14

たとえば、ページ内のいくつかのフィールドを無効にしています:(jinja2テンプレートシステムを使用)

<html>
<body>
<form action="" method=POST>
    {{ form.name(disabled=True) }}
    {{ form.title }}
    -- submit button --
</form>
</body>
</html>

期待どおり、フィールドはフォームで無効になっています。

私のviews.pyで:フォーム送信時にvalidate_on_submit()を実行すると、無効になっている「名前」フィールドの検証エラーで失敗します。検証が無効なフィールドを無視することを望んでいました。それは正しい行動ですか?もしそうなら、そのような場合の対処法を教えていただけないでしょうか?

更新しました:

class TeamForm(wtf.Form):
    name = wtf.TextField("Team Name", validators=[validators.Required()])
    title = wtf.TextField("Title", validators=[validators.Required()])
4

4 に答える 4

26

これは実際には興味深い問題であり、WTForms がこの問題を解決する方法は、意図的に明示性を必要とするものになっています。これは、セキュリティと関係があり、ユーザーが入力を偽造できないようにするためです。

つまり、「マネージャー」は名前を編集できませんが、「管理者」は編集できます。

一見すると、これは明らかなように思えます。HTML でフィールドを無効にして、ビューを次のように記述してください。

def edit_team():
    form = TeamForm(request.POST, obj=team)
    if request.POST and form.validate():
        form.populate_obj(team) # <-- This is the dangerous part here
        return redirect('/teams')
    return render('edit_team.html')

書かれているように、HTML フォームの無効なプロパティはクライアント側のみであるため、これは重大なセキュリティ リスクです。HTML インスペクター (つまり、FireBug、Webkit ドキュメント インスペクターなど) を持っている人なら誰でもこのプロパティを削除できます。または、次のような単純な要求を行うこともできます。

POST /edit_team/7 HTTP/1.0
Content-Type: application/x-urlencoded

team=EVILTEAMNAME&title=foo

問題はもちろん、これを行う適切な方法に対応して、サーバー側でこれを適切にゲートするにはどうすればよいかということです。WTForms での正しいアプローチは、最初からフィールドを持たないことです。これを行うにはいくつかの方法があります。1 つはフォーム構成を使用し、たとえば ManagerTeamForm と AdminTeamForm を使用することです (これが優れている場合もあります) が、del を使用して特定のフィールドを削除する方が簡単な場合もあります。

したがって、検証の問題がなく、ビューを作成する方法は次のとおりです。

def edit_team():
    form = TeamForm(request.POST, obj=team)
    if user.role == 'manager':
        del form.name
    if request.POST and form.validate():
        form.populate_obj(team)
        return redirect('/teams')
    return render('edit_team.html')

そして、テンプレートへの簡単な変更:

<html>
<body>
<form action="" method=POST>
    {% if 'name' in form %}
        {{ form.name() }}
    {% else %}
        {{ team.name|e }}
    {% endif %}
    {{ form.title }}
    -- submit button --
</form>
</body>
</html>

wtforms のベスト プラクティスの参考資料:

于 2013-05-15T22:51:39.307 に答える
1

この問題に対して独自のバリデーターを定義しました。

from wtforms.validators import Optional

class OptionalIfDisabled(Optional):

    def __call__(self, form, field):
        if field.render_kw is not None and field.render_kw.get('disabled', False):
            field.flags.disabled = True
            super(OptionalIfDisabled, self).__call__(form, field)

次に、フォームの新しいベースを定義しました。

from wtforms.form import Form

class BaseForm(Form):

    def populate_obj(self, obj):
        for name, field in self._fields.items():
            if not field.flags.disabled:
                field.populate_obj(obj, name)

現在、すべてのフォームは、次のようにフィールドを拡張BaseFormおよび無効化できます。

from wtforms.fields import StringField, SubmitField

class TeamForm(BaseForm):
    team = StringField(label='Team Name', 
                       validators=[OptionalIfDisabled(), InputRequired()]
    submit = SubmitField(label='Submit')

    def __init__(self, *args, **kwargs):
        super(TeamForm, self).__init__(*args, **kwargs)
        # disable the fields if you want to
        if some_condition:
            self.team.render_kw = {'disabled': True}

の検証後TeamForm、 を使用populate_objして、有効なフォーム データを任意のオブジェクトにコピーできます。無効なフィールドは無視されます。

于 2016-08-12T10:46:51.360 に答える