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

时间:2010-10-25 00:42:48

标签: django django-models django-orm

我正在继承现有模型。我希望现在父类的许多成员都是子类的成员。

例如,我有一个模型Swallow。现在,我正在制作EuropeanSwallow(Swallow)和AfricanSwallow(Swallow)。我想采取一些但不是所有Swallow对象使它们成为EuropeanSwallow或AfricanSwallow,这取决于它们是否是迁徙的。

我该如何移动它们?

5 个答案:

答案 0 :(得分:8)

这有点像黑客,但这有效:

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

答案 1 :(得分:6)

我知道这要晚得多,但我需要做类似的事情并且找不到多少。我发现答案隐藏在一些源代码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

我无法弄清楚如何使用此方法进行表单验证;所以它当然可以得到更多改善;可能意味着数据库重构可能是最好的长期解决方案......

答案 2 :(得分:1)

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

如果你想在数据库中为Swallow vs AfricanSwallow与EuropeanSwallow存储不同的信息,那么你将需要使用MTI。官方django模型推荐的MTI最大的问题是多态性无法正常工作。也就是说,如果从DB中获取Swallow对象(实际上是AfricanSwallow对象),您将无法获得非洲Swwallow实例。 (参见this question。)django-model-utils InheritanceManager之类的东西可以帮助解决这个问题。

如果您需要通过此更改保留实际数据,请使用South migrations。进行两次迁移 - 首先是一次更改模式,另一次是将相应对象的数据复制到子类中。

答案 3 :(得分:0)

我建议使用django-model-utils's InheritanceCastModel。这是我喜欢的一个实现。你可以在djangosnippets和一些博客中找到更多,但是经过他们所有我选择了这个。希望它有所帮助。

答案 4 :(得分:0)

另一种(过时的)方法:如果你不介意保留父母的身份,你可以从父母的角色创建全新的子实例。这就是我所做的:

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

一旦运行,将创建一个新的AfricanSwallow实例,替换每个初始的Swallow实例 也许这会帮助某人:)