8

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

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

我怎样才能移动它们?

4

5 回答 5

10

这有点骇人听闻,但这有效:

swallow = Swallow.objects.get(id=1)
swallow.__class__ = AfricanSwallow
# set any required AfricanSwallow fields here
swallow.save()
于 2010-10-25T04:55:59.077 回答
7

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

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

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

于 2014-01-15T23:21:23.483 回答
1

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

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

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

于 2010-11-26T20:23:46.087 回答
0

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

于 2010-10-28T14:07:41.487 回答
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()

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

于 2017-09-21T03:55:53.963 回答