4

これに関連する以前の質問に答えてくれた Insin に感謝します。

彼の答えはうまくいきましたが、「cleaned_data」の提供、またはより正確にはその使用方法に当惑していますか?

class RegistrationFormPreview(FormPreview):
    preview_template    = 'workshops/workshop_register_preview.html'
    form_template       = 'workshops/workshop_register_form.html'

    def done(self, request, cleaned_data):
        # Do something with the cleaned_data, then redirect
        # to a "success" page. 

        registration            = Registration(cleaned_data)
        registration.user       = request.user
        registration.save()
        # an attempt to work with cleaned_data throws the error: TypeError 
        # int() argument must be a string or a number, not 'dict'
        # obviously the fk are python objects(?) and not fk_id
        # but how to proceed here in an easy way?



        # the following works fine, however, it seems to be double handling the POST data
        # which had already been processed in the django.formtools.preview.post_post
        # method, and passed through to this 'done' method, which is designed to 
        # be overidden.
        '''
        form                    = self.form(request.POST)   # instansiate the form with POST data
        registration            = form.save(commit=False)   # save before adding the user
        registration.user       = request.user              # add the user
        registration.save()                                 # and save.
        '''

        return HttpResponseRedirect('/register/success')

クイック リファレンスとして、post_post メソッドの内容を次に示します。

def post_post(self, request):
    "Validates the POST data. If valid, calls done(). Else, redisplays form."
    f = self.form(request.POST, auto_id=AUTO_ID)
    if f.is_valid():
        if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
            return self.failed_hash(request) # Security hash failed.
        return self.done(request, f.cleaned_data)
    else:
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))
4

1 に答える 1

10

ModelFormでここで行っていることをこれまで試したことはありませんが、**演算子を使用して、cleaned_dataディクショナリをRegistrationコンストラクターに必要なキーワード引数に展開できる可能性があります。

   registration = Registration (**cleaned_data)

モデルクラスのコンストラクターは、DjangoのModelメタクラスが結果のオブジェクトのインスタンスレベルの属性に変換するキーワード引数を取ります。**演算子は、辞書をこれらのキーワード引数に拡張するようにPythonに指示する呼び出し規約です。

言い換えると...

あなたが現在していることはこれに等しいです:

registration = Registration ({'key':'value', ...})

コンストラクターは、キーワード引数を含む辞書ではなく、キーワード引数を予期しているため、これは必要なことではありません。

あなたがしたいのはこれです

registration = Registration (key='value', ...)

これはこれに類似しています:

registration = Registration (**{'key':'value', ...})

繰り返しになりますが、私は試したことがありませんが、Registrationコンストラクターで予期されていない新しい属性をフォームに追加するなど、フォームで特別なことをしていなければ機能するようです。その場合、これを行う前に、cleaned_dataディクショナリの項目を変更する必要があります。

ただし、フォームプレビューユーティリティを使用することで、ModelFormsに固有の機能の一部を失っているように見えます。おそらく、ユースケースをDjangoメーリングリストに持っていき、ModelFormsでの動作を改善する可能性のあるこのAPIの潜在的な拡張機能があるかどうかを確認する必要があります。

編集

上記で説明した内容を除いて、cleaned_dataディクショナリからフィールドを「手動で」抽出し、Registrationコンストラクターに渡すこともできますが、新しいコードを追加するときにこのコードを更新することを忘れないでください。モデルへのフィールド。

registration = Registration (
    x=cleaned_data['x'],
    y=cleaned_data['y'],
    z=cleaned_data['z'],
    ...
)
于 2009-03-09T23:46:11.767 に答える