Django - 动态导入模型表单

时间:2012-02-13 16:37:41

标签: django

我想创建一个能够为各种不同模型显示ModelForm的视图。它通过获取模型的内容类型然后动态实例化与该特定模型相关联的模型表单来实现。这是我的模特:

from django.db import models

class SomeModel(models.Model):
    name = models.CharField(max_length=150)

    def __unicode__(self):
        return self.name

在同一个应用程序中,有一个forms.py,其格式如下:

from django.forms import ModelForm

from someapp.models import SomeModel 

class SomeModelForm(ModelForm):
    class Meta:
        model = SomeModel
        fields = ('name',)

所以我想在我的视图文件中做的是动态地为每个模型返回正确的表单。我尝试了以下方法:

from django.db import models
from someapp.forms import SomeModelForm

    class SomeModel(models.Model):
        name = models.CharField(max_length=150)

        form = SomeModelForm

        def __unicode__(self):
            return self.name

但由于明显的循环导入,它不起作用。有谁知道如何实现这个目标?我尝试使用modelform_factory,但它似乎忽略了我在forms.py中的任何自定义模型形式。

编辑:我应该提到我不会有模型的实例,只有模型类本身,所以有一个方法在模型内部不起作用(它确实但是,如果您在模型的实例上调用它,则可以工作)

4 个答案:

答案 0 :(得分:6)

您可以通过在方法中导入模型表单来绕过循环导入。

class SomeModel(models.Model):
    name = models.CharField(max_length=150)

    @staticmethod
    def get_form_class():
        from someapp.forms import SomeModelForm
        return SomeModelForm

# in your view:
SomeModel.get_form_class()

答案 1 :(得分:3)

将导入放在模型上的方法中应该足以让你绕过循环导入,所以你可以使用:

而不是你拥有的东西。
class SomeModel(models.Model):
    ...
    def get_form(self):
        from someapp.forms import SomeModelForm
        return SomeModelForm

如果您需要,您甚至可以将其作为财产:

form = property(get_form)

答案 2 :(得分:3)

对于延迟导入模型,有一个内置函数get_model

from django.db.models import get_model
SomeModel = get_model('your_app_name', 'SomeModel')

答案 3 :(得分:0)

使用__import__getattr

# models.py
class SomeModel(models.Model):
    ...
    @classmethod
    def get_form(cls):
        try:
            app = __import__(cls._meta.app_label)
            forms = getattr(app, "forms")
            return getattr(forms, "%sForm" % cls.__name__)
        except:
            return None

# forms.py
class SomeModelForm(forms.Form):
    ...

在视图中,您可以将表单关联到这样的模型:

# views.p 
from models import SomeModel
...

def myview(request):
    form = SomeModel.getform()