将 python / django 对象从父模型移动到子模型(子类)

问题描述 投票:0回答:5

我正在对现有模型进行子类化。我希望父类的许多成员现在成为子类的成员。

例如,我有一个模型燕子。现在,我正在制作欧洲燕子(燕子)和非洲燕子(燕子)。我想要一些但不是所有的燕子对象使它们成为欧洲燕子或非洲燕子,具体取决于它们是否是迁徙的。

我怎样才能移动它们?

django django-models django-orm
5个回答
11
投票

我知道这是很久以后的事了,但我需要做类似的事情,但找不到太多。我在一些源代码中找到了答案here,但也编写了一个示例类方法就足够了。

class AfricanSwallow(Swallow):

    @classmethod
    def save_child_from_parent(cls, swallow, new_attrs):
        """
        Inputs:
        - swallow: instance of Swallow we want to create into AfricanSwallow
        - new_attrs: dictionary of new attributes for AfricanSwallow

        Adapted from: 
        https://github.com/lsaffre/lino/blob/master/lino/utils/mti.py
        """
        parent_link_field = AfricanSwallow._meta.parents.get(swallow.__class__, None)
        new_attrs[parent_link_field.name] = swallow
        for field in swallow._meta.fields:
            new_attrs[field.name] = getattr(swallow, field.name)
        s = AfricanSwallow(**new_attrs)
        s.save()
        return s

但是我不知道如何让我的表单验证与此方法一起使用;所以它肯定可以进一步改进;可能意味着数据库重构可能是最好的长期解决方案......


11
投票

这有点麻烦,但这很有效:

swallow = Swallow.objects.get(id=1)
swallow.__class__ = AfricanSwallow
# set any required AfricanSwallow fields here
swallow.save()

1
投票

取决于您将使用哪种模型继承。看 http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance 对于三种经典类型。因为听起来您想要 Swallow 对象来排除抽象基类。

如果您想在数据库中存储 Swallow、AfricanSwallow、EuropeanSwallow 的不同信息,那么您将需要使用 MTI。正如官方 django 模型所建议的那样,MTI 的最大问题是多态性无法正常工作。也就是说,如果您从数据库中获取一个 Swallow 对象,而该对象实际上是一个 AfricanSwallow 对象,那么您将不会获得 AfricanSwallow 的实例。 (参见这个问题。)像 django-model-utils InheritanceManager 这样的东西可以帮助克服这个问题。

如果您有需要通过此更改保留的实际数据,请使用南迁移。进行两次迁移——第一个迁移更改架构,另一个迁移将适当的对象数据复制到子类中。


0
投票

另一种(过时的)方法:如果您不介意保留父级的 id,您可以根据父级的 attrs 创建全新的子实例。这就是我所做的:

ids = [s.pk for s in Swallow.objects.all()]
# I get ids list to avoid memory leak with long lists
for i in ids:
    p = Swallow.objects.get(pk=i)
    c = AfricanSwallow(att1=p.att1, att2=p.att2.....)
    p.delete()
    c.save()

运行后,将创建一个新的 AfricaSwallow 实例来替换每个初始 Swallow 实例 也许这会对某人有所帮助:)


0
投票

我建议使用django-model-utils的InheritanceCastModel。这是我喜欢的一种实现。您可以在 djangosnippets 和一些博客中找到更多内容,但在浏览完所有内容后,我选择了这个。希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.