如何动态制作一个现有的非抽象django模型,抽象?

时间:2016-11-02 09:01:28

标签: python django django-models

我认为我或多或少有一个非正统和黑客的问题。我目前拥有的是包含多个应用程序的django项目。 我想使用一个应用程序non-abstract model (ModelA)app1)并通过子类化将其用于另一个应用程序(app2)。 App1的型号 不应该迁移到数据库,我只想通过扩展其功能和逻辑来使用app1及其模型类的功能。 我通过将这两个应用添加到settings.INSTALLED_APPS,并阻止app1的模型迁移到数据库来实现这一目标。

INSTALLED_APPS += (
    'App1',
    'App2',
)

# This is needed to just use App1's models
# without creating it's database tables
# See: http://stackoverflow.com/a/35921487/1230358
MIGRATION_MODULES = {
    'App1': None,
}

到目前为止,这么好,丑陋和hackish,我知道......现在剩下的问题是app1的大部分模型都是非抽象的(ModelA),如果我尝试的话 要对它们进行子类化,ModelA的所有字段都不会填充到db中,而是填入名为app2_modelb的表中。这对我来说很清楚,因为我排除了App1 迁移到数据库,因此数据库中完全缺少表app1_modela。

我现在的想法是克隆ModelA,保留其所有功能,并将其元信息从非抽象更改为抽象(ModelB.Meta.abstract = True)。 我希望通过这种方式,ModelA的所有原始字段都将继承到ModelB,并且可以在其各自的DB表和列(app1_modelb)中找到。

我现在拥有的是:

# In app1 -> models.py
class ModelA(models.Model):
    title = models.CharField(_('title'), max_length=255)
    subtitle =  models.CharField(_('subtitle'), max_length=255)

    class Meta:
        abstract = False # just explicitly for demonstration


# In app2 -> models.py
from app1.models import ModelA

class ModelB(ModelA):
    pass
    # Just extending ModelAdoes not create the fields title and subtitle fields in app2_modelb
    # because ModelA.meta.abstract = False

制作现有非抽象模型摘要的当前方式(伪代码)如下所示:

# In app2 -> models.py
from app1.models import ModelA

def get_abstract_class(cls):
    o = dict(cls.__dict__)
    o['_meta'].abstract = True
    o['_meta'].app_label = 'app2'
    o['__module__'] = 'app2.models'

    #return type('Abstract{}'.format(cls.__name__), cls.__bases__, o)
    return type('Abstract{}'.format(cls.__name__), (cls,), o)

ModelB = get_abstract_class(ModelA)

class ModelC(ModelB):
    # title and subtitle are inherited from ModelA
    description = models.CharField(_('description'), max_length=255)

这不起作用,在这个冗长的描述之后我的(简单)问题是,是否可以克隆非抽象模型类,保留其所有功能以及如何将其更改为抽象?

要清楚。所有上层模糊都是关于,我无法更改app1中的任何代码。可能是app1是通过pip安装的django应用程序。

1 个答案:

答案 0 :(得分:0)

为什么不,在app1

AbstractBaseModelA(models.Model):
    # other stuff here
    class Meta:
        is_abstract=True


ModelA(AbstractBaseModelA):
    # stuff
app2中的

MobelB(AbstractBaseModelA):
    # stuff

很抱歉,如果我误解了你的目标,但我认为上述结果应达到同样的效果。