7

Pycharm を使用して Django でフォーム検証をデバッグしようとしています。ImageField を介してアップロードした画像でフォームの検証が失敗し、なぜ失敗したのかを知りたいです。ただし、検証プロセスをデバッグし、POST データを使用してフォームの初期化を実行しようとするたびに、検証を試みず、フォーム データをデータベース。それは私を夢中にさせています...個々のステップを観察するかどうかに応じて、どのように行動が変わるのでしょうか? また、たとえば BaseForm クラスの完全クリーン メソッドの実行中に、いくつかのブレーク ポイントを設定しようとしましたが、そこに到達することはないようです。

編集:ここにいくつかのコードがあります

私のモデルとフォーム:

class Car(models.Model):
    ...
    image = models.ImageField(upload_to='car_images/',blank=True,null=True)

class CarForm(ModelForm):
    class Meta:
        model = Car

私の見解:

def create_car(request):
    if request.method == 'POST':
        car_form = CarForm(request.POST,request.FILES)
        if car_form.is_valid():
            ...
4

1 に答える 1

6

これは本当に苦痛です。この問題は 2 回発生しましたが、まだ適切な解決策が見つかりません。

__init__これは、フォームのメソッドをオーバーライドする場合の安全なデバッグの例です。

class MyForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

        # Disable form validation for debugging purposes unless the
        # object is fully initialized. Set breakpoints BELOW this line.
        del self._errors

        # Write some additional initializations here, debug safely.
        ...

        # Initialization is finished. Enable form validation.
        self._errors = None

基本フォーム クラスをデバッグする場合は、同じ方法で Django コードにパッチを適用します。

デバッグ後にこの追加コードを残すか削除することができます - これは大きな違いはありません。ただし、将来これが必要になる場合に備えて残しておくことをお勧めします。

それで、ここで実際に何が起こっているのですか?

(Django プロジェクト サイトのバグレポート: https://code.djangoproject.com/ticket/24710 )

問題は、Django のBaseForm.errorsプロパティ ゲッター (実際には@propertyデコレータを使用したメソッド) が多すぎることです。プロパティ値full_clean()を変更するメソッドを呼び出して、 getter が呼び出しを繰り返しても同じ作業を繰り返さないようにします。_errorserrors

class BaseForm(object):

    @property
    def errors(self):
        if self._errors is None:
            self.full_clean()
        return self._errors

    def full_clean(self):
        self._errors = ErrorDict()
        ...

もちろん、PyCharm デバッガーはプロパティが単なるプロパティであると想定しており、オブジェクトの内部状態に重大な変更を加えることはありません。そのため、デバッガーはerrorsゲッターを呼び出して、メソッドをデバッグするときに「変数」ウィンドウにその値を表示します__ini__。これにより、通常の実行フローが中断されます。

get_error()(これが、プロパティではなく、このような場合のようなメソッドを定義する必要がある理由です)

__init__考えられる 1 つの提案は、フォームのメソッド内でのブレークポイントと段階的な実行を避けることです。ただし、本当にデバッグする必要がある場合は、コードを変更して_errors、段階的な実行中にプロパティが存在しないようにします。full_cleanこれにより、メソッドの呼び出しが防止されます。PyCharm デバッガーは、プロパティにアクセスしようとするたびにエラーを受け取りますerrors

:プロパティは、メソッドerrorsの外部であっても、実行が一時停止されている任意のステップで評価される場合があります。__init__すべてのフィールドがすでに完全に初期化されている場合、これはおそらく結果に影響しません (メソッドでのみこれを行うことを忘れないでください__init__)。is_validただし、メソッド呼び出しに到達する前にフォームが検証されたように見えるため、フォーム検証プロセスをデバッグできない場合があります。この場合、full_cleanメソッド内にブレークポイントを設定し、フォームのインスタンス化ポイントとこのブレークポイントの間で停止しないでください。

于 2015-04-26T20:56:39.960 に答える