2

質問: モデルの継承を使用し、レンダリング時に子モデルごとに異なるデフォルト値が必要な場合、フィールドの初期値を指定する推奨される方法は何ModelFormですか?

としてレンダリングするときにCompileCommandとの両方が異なる初期値を必要とする次のモデルを例にとります。TestCommandModelForm

# ------ models.py
class ShellCommand(models.Model):
    command   = models.Charfield(_("command"), max_length=100)
    arguments = models.Charfield(_("arguments"), max_length=100)

class CompileCommand(ShellCommand):
    # ... default command should be "make"

class TestCommand(ShellCommand):
    # ... default: command = "make", arguments = "test"

フォームをインスタンス化するときに引数を使用できることは承知してinitial={...}いますが、モデルのコンテキスト内 (または少なくとも関連付けられた ModelForm 内) に初期値を格納することをお勧めします。

私の現在のアプローチ

私が現在行っているのは、初期値の dict を に格納Metaし、ビューでそれをチェックすることです。

# ----- forms.py
class CompileCommandForm(forms.ModelForm):
    class Meta:
        model = CompileCommand
        initial_values = {"command":"make"}

class TestCommandForm(forms.ModelForm):
    class Meta:
        model = TestCommand
        initial_values = {"command":"make", "arguments":"test"}


# ------ in views
FORM_LOOKUP = { "compile": CompileCommandFomr, "test": TestCommandForm }
CmdForm = FORM_LOOKUP.get(command_type, None)
# ...
initial = getattr(CmdForm, "initial_values", {})
form = CmdForm(initial=initial)

これはハックのように感じます。これを達成するためのより一般的/より良い方法を切望しています。提案をいただければ幸いです。

更新されたソリューション(有望に見えます)

ビューに余分な定型コードを必要とせずforms.pyに設定できるようになりました。ユーザーが引数Meta.default_initial_valuesを指定しない場合、デフォルト値が使用されます。initial={...}

class ModelFormWithDefaults(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        if hasattr(self.Meta, "default_initial_values"):
            kwargs.setdefault("initial", self.Meta.default_initial_values)
        super(ModelFormWithDefaults, self).__init__(*args, **kwargs)

class TestCommandForm(ModelFormWithDefaults):
    class Meta:
        model = TestCommand
        default_initial_values = {"command":"make", "arguments":"test"}
4

1 に答える 1

1

フォームの初期化に送信する必要がある場合、フォームのメタに initial_values を設定することにあまり使用されません。

むしろ、コンストラクター メソッドをオーバーライドする ModelForm のサブクラスを作成し、そのサブクラスを他のフォームの親クラスとして使用します。

例えば

class InitialModelForm(forms.ModelForm):
    #here you override the constructor
    pass

class TestCommandForm(InitialModelForm):
    #form meta

class CompileCommandForm(InitialModelForm):
    #form meta
于 2011-02-02T15:08:59.063 に答える