我有几个MyModel,都来自相同的MyBaseModel,并且对于每个模型,还有一个从MyModelBaseForm派生的MyModelForm。 给定MyModelForm,我可以通过MyModelForm._meta.model访问相关模型。 最简单的反向方法是:给定一个MyModel,获取相应的MyModelForm?
原因是我想在视图中使用duck typing:
from django.db import models
def edit_view(request, my_model_name, pk=None):
my_model = my_model_registry[my_model_name]
instance = get_object_or_404(my_model, pk=pk) if pk else None
my_model_form = my_model._meta.modelform
# or my_model_form = my_model_form_registry[my_model]
form = my_model_form(request.POST or None, instance=instance)
if form.is_valid():
instance = form.save()
return HttpResponseRedirect(instance.get_absolute_url())
return render(request, 'my_template', {'form': form, 'instance': instance})
my_model_registry = dict( (Model._meta.verbose_name, Model) for Model in
models.get_models() if issubclass(Model, MyBaseModel)
)
理想的解决方案是使用字典my_model_form_registry[my_model]
,以便我可以像查看模型一样查找表单。我知道我可以通过明确设置
my_model_form_registry[MyModelForm._meta.model] = MyModelForm
在每个MyModelForm定义之后,但是在DRY的精神下,我想为ModelBaseForm执行一次,并为所有派生模型自动执行。
元类可以做到这一点,但我不能让它工作,因为model.ModelForm已经有一个特殊的元类。
另一种选择是,如果有models.get_models
的等价物,但是对于模型形式。那存在吗?
答案 0 :(得分:3)
django.forms.models
中有modelform_factory()
函数,它在给定模型类的情况下动态构造ModelForm类,听起来它可以做你想要的。
答案 1 :(得分:0)
我想我已经想出了如何将Metaclass添加到MyModelBaseForm 这将解决问题:
class MyModelBaseForm(forms.ModelForm):
class __metaclass__(forms.ModelForm.__metaclass__):
"""
Metaclass to register the modelform with the model,
as model._meta.modelform.
"""
def __init__(cls, name, bases, dic):
super(__metaclass__, cls).__init__(cls, name, bases, dic)
cls._meta.model._meta.modelform = cls
class Meta:
model = MyBaseModel
fields = [ ... ]