1

次のように、モデルの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だから私は、

  1. 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実際のモデルフィールドに値を挿入しています。

これが何が起こるかです。

  1. ユーザーがフォームに入力し、[プレビュー] をクリックします。
  2. これにより、security_hashその特定のフォームの が作成され、プレビュー ビューがレンダリングされます。
  3. フォームに問題がない場合、ユーザーはフォームを再度送信します。それ以外の場合は、編集ボタンをクリックしてフォームを再度編集します。

フォームに問題がなく、ユーザーが送信ボタンをクリックすると、フォームを送信する代わりにフォームプレビューがプレビューにループバックします。次に、プレビュー テンプレートで送信ボタンをもう一度クリックすると、フォームが送信されます。

これはおそらく、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()FormPreviewpreview_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()メソッドはまだ呼び出されており、ループはまだ存在しています。:(

4

0 に答える 0