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

时间:2022-12-24 23:47:43

I think I have a more or less unorthodox and hackish question for you. What I currently have is django project with multiple apps. I want to use a non-abstract model (ModelA) of one app (app1) and use it in another app (app2) by subclassing it. App1's models should not be migrated to the DB, I just want to use the capabilities of app1 and it's model classes, by extending its functionality and logic. I achieved that by adding both apps to settings.INSTALLED_APPS, and preventing app1's models being migrated to the DB.

我想我或多或少有一个非正统和黑客的问题。我目前拥有的是具有多个应用程序的django项目。我想使用一个应用程序(app1)的非抽象模型(ModelA),并通过继承它在另一个应用程序(app2)中使用它。 App1的模型不应该迁移到DB,我只想通过扩展其功能和逻辑来使用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://*.com/a/35921487/1230358
MIGRATION_MODULES = {
    'App1': None,
}

So far so good, ugly and hackish, I know... The remaining problem is now that most of app1's models are non-abstract (ModelA) and if I try to subclass them, none of the ModelA's fields get populated to the db into the table named app2_modelb. This is clear to me, because I excluded the App1 from migrating to the DB and therefore the table app1_modela is completely missing in the DB.

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

My idea now was to clone ModelA, preserve all its functionallity, and changing it's Meta information from non-abstract to abstract (ModelB.Meta.abstract = True). I hope that by this, all the original fields of ModelA will be inherited to ModelB and can be found in its respective DB table and columns (app1_modelb).

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

What I have right now is:

我现在拥有的是:

# 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

My current way (pseudo code) to make an existing non-abstract model abstract looks like this:

我现有的非抽象模型抽象方式(伪代码)如下所示:

# 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)

This does not work, and after this lengthy description my (simple) question would be, if and how is it possible to clone a non-abstract model class preserving all its functionality and how to change it to be abstract?

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

Just to be clear. All upper fuzz is about, that I can't change any code in app1. May it be that app1 is a django app installed via pip.

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

1 个解决方案

#1


0  

Why not, in app1

为什么不,在app1

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


ModelA(AbstractBaseModelA):
    # stuff

in app2:

在app2中:

MobelB(AbstractBaseModelA):
    # stuff

Sorry if I've misunderstood your aims, but I think the above should achieve the same end result.

对不起,如果我误解了你的目标,但我认为上面应该达到同样的最终结果。

#1


0  

Why not, in app1

为什么不,在app1

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


ModelA(AbstractBaseModelA):
    # stuff

in app2:

在app2中:

MobelB(AbstractBaseModelA):
    # stuff

Sorry if I've misunderstood your aims, but I think the above should achieve the same end result.

对不起,如果我误解了你的目标,但我认为上面应该达到同样的最终结果。