3

フィールドが SelectField である WTForms を使用して、現在の値が有効でない場合 (たとえば、定義されたオプションのインスタンスではない場合) に他の何かをチェックする特別な (カスタム) 検証を行うフォームを作成したいと考えています。

ドキュメントで、それを行う正しい方法は、関数をオーバーライドするpre_validateか、必要に応じて行うことであると読みましたpost_validate

したがって、私のアプローチは次のとおりです。

1 - MySelectForm という新しいフィールドを作成します。

class MySelectField(SelectField):
    def post_validate(self, form, validation_stopped):
        """overrides post validation"""
        #Here is my custom validation

2-フォームで元のフィールドの代わりにこのフィールドを使用します

私が理解できないのは、ドキュメントで読んだように、post_validate「フィールドが属するフォーム」という入力を受け取る場合、インスタンスであるフィールドの現在の値にアクセスするにはどうすればよいMySelectFieldですか?

言い換えれば、誰かが or をオーバーライドする方法の例を作ることができますpre_validatepost_validate?

4

2 に答える 2

0

メソッドに渡してselfいるので、フィールド オブジェクトを使用できます。これは WTForms のFieldクラスを継承しているため、利用できるはず field.dataです。これには、「いずれかのプロセス メソッドを呼び出した結果の (サニタイズされた) 値」が含まれます。

于 2013-08-07T21:34:26.340 に答える
0

以下はソースコードの一部です

# wtforms.fields.core.py  |  version: Flask-WTF 0.14.3

class Field(object):
    errors = tuple()
    ...

    def validate(self, form, extra_validators=tuple()):
        self.errors = list(self.process_errors)
        stop_validation = False

        self.check_validators(extra_validators)

        try:
            self.pre_validate(form)   # <---------- focus here
        except StopValidation as e:
            if e.args and e.args[0]:
                self.errors.append(e.args[0])
            stop_validation = True
        except ValueError as e:
            self.errors.append(e.args[0])

        # Run validators
        if not stop_validation:
            chain = itertools.chain(self.validators, extra_validators)
            stop_validation = self._run_validation_chain(form, chain)  # <-- It will run ``InputRequired, YourValidators1, YourValidators2, validate_username``  (see the example code)

        # Call post_validate
        try:
            self.post_validate(form, stop_validation)  # <---------- focus here
        except ValueError as e:
            self.errors.append(e.args[0])

        return len(self.errors) == 0

そして、私はあなたに例を挙げますpost_validate(これpre_validateは非常に似ており、あなたは自分でそれを行うことができると信じています)

from flask_wtf import FlaskForm, Form
from wtforms import StringField, ValidationError, StopValidation
from wtforms.validators import InputRequired
from typing import List


class StateStringField(StringField):
    ok_msg_list: List = None  # Because class ``wtforms.fields.core.Field`` are not existed any attributes I like, so I create one.

    def post_validate(self, form: Form, stop_validation: bool):
        if self.ok_msg_list is None:
            self.ok_msg_list = []
        if stop_validation:
            return
        if not 'errors':  # assume no errors...
            raise ValueError('...')
        else:
            self.ok_msg_list.append('OK')


class UserForm(FlaskForm):
    username = StateStringField('User',
                                validators=[InputRequired(),
                                            # YourValidators2, YourValidators3
                                            ])

    def validate_username(self, field: StringField):
        if len(field.data) > 50:
            raise StopValidation('Name must be less than 50 characters')
<!-- templates/auth/register.html-->
<form method="post">   
    {{ form.hidden_tag() }}
    <p>{{ form.username.label }} {{ form.username()|safe }}
      {% if form.username.errors %}
        {% for error in form.username.errors %}
          <p style="color:red;">{{ error }}<p>
        {% endfor %}
      {% endif %}

      {% if form.username['ok_msg_list'] %}  <!-- similar as python: if hasattr('ok_msg_list') -->
        {% for ok_msg in form.username.ok_msg_list %}
          <span style="color:blue;">{{ ok_msg|safe }}</span>
        {% endfor %}
      {% endif %}
    </p>
</form>

概要

すべてpost_validateの検証が実行された後、別の検証を実行する場合に使用できます。(個人的には に似ていると思います。post_validatefinally

私の例では、ユーザーがすべての検証が正しいことを確認すると、その横に OK メッセージが表示されます。

ここに画像の説明を入力

于 2020-11-12T08:23:19.983 に答える