Django使用Model注册ModelForm

时间:2014-09-16 19:26:36

标签: python django metaclass modelform

我有几个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的等价物,但是对于模型形式。那存在吗?

2 个答案:

答案 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 = [ ... ]