0

私のモデルでは、次のものがあります

--- models.py ---
class A(models.Model):
   my_Bs = models.ManyToManyField('B', through='AlinksB')
   ...

class B(models.Model):
   ...

class AlinksB(models.Model):
   my_A = models.ForeignKey(A)
   my_B = models.models.ForeignKey(B)
   order = models.IntegerField()

対応する管理者も同様です (管理者ビューには B インスタンスをリンクするためのインラインがあり、このインラインのフォームセットとフォームをカスタマイズするために必要なものを用意しました):

--- admin.py ---
class AlinksBInlineForm(forms.ModelForm):
   class Meta:
      model = AlinksB

class AlinksBInlineFormset(forms.models.BaseInlineFormSet): # there also is a BaseModelFormset
   form = AlinksBInlineForm

class AlinksBInline(admin.TabularInline):
   formset = AlinksBInlineFormset
   model = AlinksB

class AAdmin(admin.ModelAdmin):
   form = AForm
   inlines = (AlinksBInline,)
   ...

class BAdmin(admin.ModelAdmin):
   ...

フォームのバリデーションをカスタマイズするには、難しいことは何もありません。フォーム オブジェクトの「クリーン」メソッドをオーバーライドするだけです。フォームセットに多くの異なるフォームが必要な場合は、フォームセットの「 init」メソッドで手動で変更するだけでよいと思います。しかし、フォームセットをクリーンアップするときにすべてのフォームをプログラムで検証するのはどうでしょうか。

私の場合:すべての注文(インライン行を除外して削除する)が空の場合、自動インクリメントで「注文」フィールド(A管理ビューのインライン)を自動的に設定する方法?!

4

1 に答える 1

3

Django Framework でのフォームセットの検証中に自動フォーム クリーニングを実行しようとすることについて、Google で多くの時間を費やしました。数日後、解決策を見つけることができなかったので、フィールド、ウィジェット、フォーム、およびフォームセットがどのように機能するかを確認するために、Django のソース コードを調べ始めました。

これが私が理解したものです:

- ユーザーがフォームセットを送信するときに POST したすべてのデータは、フォームセットの「data」属性に保存されます。この属性は非常に見苦しく、直接使用することはできません。- フォームはフィールドの単なるラッパーです (すべてのフィールドの clean メソッドを呼び出し、エラー バッファーを埋めます。その他はわずかです)。

-フォーム フィールドにはウィジェットがあります。このウィジェットを使用すると、フォームセットの「データ」属性からフィールドの生の値を取得できます

form.add_prefix('field name') # returns the 'field prefix', the key of formset.data used to retrieve the field's raw value
form.fields['field name'].widget.value_from_datadict(form.data, form.files, 'field prefix') # returns the raw value

-フォームフィールドには、生の値を正しい python 値に変換するメソッドもあります (私の場合: order は整数で、フィールドが空のままの場合は None です)

form.fields['field name'].to_python(raw_value) # returns a value with the right type

-次のコードを使用して、フォームセットのいずれかのフィールドの値を変更できます

form.data.__setitem__('field prefix', value) # code to update an iterable knowing the key to change

-フィールドの値を変更したら、フォームの「full_clean」メソッドを呼び出して、フォームのクリーニングを再試行できます (これにより、以前のエラーが削除されます)。

-フォームを再度検証したら、" full_clean " メソッドを使用してフォームセットの検証を再試行することもできます。ただし、無限ループを避けるように注意してください

- フォームまたはフォームセットにさらにエラー メッセージを追加するために、読み取り専用データを持つフォーム クリーン データのみを使用できます。

別の解決策は、「form.clean_data」属性を手動で変更し、formset.errors とすべての form.errors を消去することです。

私と同じ状況の誰かに役立つことを願っています!

リコラ3D

于 2013-04-10T08:11:56.427 に答える