M_1、...、M_n、...、M_2n というモデルがたくさんあるので、合計で 2n 個のモデルがあるとします。最初の n 個のモデルのそれぞれには、最後の n 個のモデルのモデルを参照する (必須の) 外部キーがあります。したがって、モデル M_x がモデル M_2x への (必須の) 外部キー FK_x を持っているとします。ここで、1 <= x <= n です。
各モデル M_x (1 <= x <= n) について、モデル フォーム MF_x を使用したいと考えています。FK_x がフォームに表示されないように、MF_x が外部キー FK_x を除外する必要があります。ただし、FK_x は必須フィールドであるため、次のようにフォームのインスタンス化でフィールドを指定する必要があります。
model_2x_instance = M_2x.objects.create(**some_data)
model_x_instance = M_x(FK_x=model_2x_instance, ...)
form_x_instance = MF_x(instance=model_x_instance)
次に、MF_x の __init__ は次のことを実行して、'instance' 引数が指定され、モデル M_2x への外部キー FK_x が設定されていることを確認します。
def __init__(self, *args, **kwargs):
instance = kwargs.get('instance', None)
if not instance:
raise InstanceRequiredError
if not hasattr(instance, 'FK_x') or not instance.FK_x:
raise ForeignKeyRequiredError
...
MF_x の clean メソッドは、フォームが M_x インスタンスを作成/変更できるように、除外された FK_x をcleaned_data ディクショナリに戻します。
def clean(self):
self.cleaned_data.update(FK_x=self.instance.FK_x)
return super(...).clean()
ここでの問題は、これらのモデル フォームごとに 2 つのコード スニペットを繰り返したくないということです。しかし、すべてが DRY になるようにこれをリファクタリングするきちんとした方法は思いつきません。
私がこのようなものを書くことができれば:
class Meta:
exclude_but_require_and_inject_later = 'FK_x'
すべてのモデル フォーム MF_x (1 <= x <= n) の共通基本クラスは、そのような除外フィールドごとに上記のコード スニペットを適用できます。しかし、独自のキーワードで Meta クラスを拡張することは (合理的に) 不可能です。