次のように、モデルの1つに3つの整数フィールドがあります。
class SomeModel(models.Model):
min_age = models.IntegerField()
max_age = models.IntegerField()
savings = helpers.MoneyField()
MoneyField は、フォームで金額 (170000) を 100000 (Lakhs) と (70000) の 2 つのドロップダウンに分割するウィジェットを使用するカスタム フィールドです。
上記のお金のフィールドを使用するフォームの場合、form preview
投稿する前にユーザーにフォームのプレビューを強制するビューがあります。
同じアイデアを使用して、単一のウィジェットを使用するように変更min_age
したいと考えました。max_age
だから私は、
AgeFields (次の複数値フィールド) が追加されました。
クラス AgeField(forms.MultiValueField):
def __init__(self, *args, **kwargs): """ Have to pass a list of field types to the constructor, else we won't get any data to our compress method. """ all_fields = ( forms.CharField(), forms.CharField(), ) super(AgeField, self).__init__(all_fields, *args, **kwargs) def compress(self, values): if values: print values return '|'.join(values) return ''
次に、フォームで、モデル フィールドを非表示にし、上記のフィールドを使用して、に似たカスタム ウィジェットを使用します。MoneyWidget()
class PostForm(forms.ModelForm):
age = AgeField(widget=widgets.AgeWidget(),
required=False)
def is_valid(self):
return super(PostForm, self).is_valid()
def full_clean(self, *args, **kwargs):
print self.data
if 'age_0' in self.data:
newdata = self.data.copy()
newdata['min_age'] = self.data['age_0']
newdata['max_age'] = self.data['age_1']
print newdata
self.data = newdata
super(PostForm, self).full_clean(*args, **kwargs)
class Meta:
model = models.SomeModel
fields = (
'age', 'min_age', 'max_age',
'savings'
)
widgets = {
'min_age' : forms.HiddenInput(),
'max_age' : forms.HiddenInput(),
'savings' : widgets.MoneyWidget(),
}
FormPreview
ループが作成されますが、現在すべてが期待どおりに機能します。上記の方法を使用して、full_clean
実際のモデルフィールドに値を挿入しています。
これが何が起こるかです。
- ユーザーがフォームに入力し、[プレビュー] をクリックします。
- これにより、
security_hash
その特定のフォームの が作成され、プレビュー ビューがレンダリングされます。 - フォームに問題がない場合、ユーザーはフォームを再度送信します。それ以外の場合は、編集ボタンをクリックしてフォームを再度編集します。
フォームに問題がなく、ユーザーが送信ボタンをクリックすると、フォームを送信する代わりにフォームプレビューがプレビューにループバックします。次に、プレビュー テンプレートで送信ボタンをもう一度クリックすると、フォームが送信されます。
これはおそらく、security_hash が生成された後に、上記の full_clean メソッドでmin_age
との値を設定したためです。max_age
上記のメソッドは、データを操作しているときに security_hash を変更します。
2 回目は、ユーザーがフォームを送信します。min_age
フィールドにmax_age
はすでに同じデータがあるため、security_hash
同じままです。
security_hash を操作する方法、または security_hash が生成される前に min_age と max_age に値を挿入する方法はありますか? それは同じままですか?
上記を達成するための最良のアプローチは何ですか?
どんな提案でも大歓迎です。ありがとう。
アップデート:
セキュリティハッシュが失敗していると想定していたので、もう少し詳しく調べてみました。したがって、ビューをfailed_hash()
呼び出す前にメソッドをオーバーライドしてエラーメッセージを出力し、呼び出されたメソッドが何であるかを推測し、フォームをメソッドにリダイレクトするようにします。preview_post()
FormPreview
preview_post()
POST
上記のメソッドでデータを操作していたときにセキュリティ ハッシュが一致しないと思ったfull_clean()
ので、min_age と max_ageを設定し、次のようにメソッドrequired=False
で値を明示的に設定しようとしましたsave()
def save(self, *args, **kwargs):
if 'age_0' in self.data:
newdata = self.data.copy()
newdata['min_age'] = self.data['age_0']
newdata['max_age'] = self.data['age_1']
self.data = newdata
super(PostForm, self).save(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(PostForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields['min_age'].required = False
self.fields['max_age'].required = False
しかし、まだ運がありません。failed_hash()
メソッドはまだ呼び出されており、ループはまだ存在しています。:(