假设我有一堆模型 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。我要求 MF_x 排除外键 FK_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__ 然后执行以下操作以检查是否给出了“实例”参数并且具有模型 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 方法然后将排除的 FK_x 注入到 clean_data 字典中,这样表单就可以创建/修改 M_x 实例:
def clean(self):
self.cleaned_data.update(FK_x=self.instance.FK_x)
return super(...).clean()
现在的问题是,我不想为每个模型表单重复两个代码片段。但是我想不出一种巧妙的方法来重构它,使一切都干燥。
如果我能写出这样的东西:
class Meta:
exclude_but_require_and_inject_later = 'FK_x'
所有模型形式 MF_x (1 <= x <= n) 的通用基类可以为每个此类排除字段应用上面的代码片段。但是(合理地)不可能使用自己的关键字扩展 Meta 类。