2010-10-25 46 views
5

我继承现有的模型。现在我想让许多父类的成员成为子类的成员。移动从父模型蟒蛇/ Django的对象一个孩子(子类)

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

我该如何移动它们?

回答

4

我知道这是晚得多,但我需要做同样的事情,找不到了。我在一些源代码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 

我找不出如何让我的表单验证使用这种方法,但是;所以肯定可以进一步改善;可能意味着一个数据库重构可能是最好的长期解决方案...

+0

嘿 - 真棒的答案。自从我有这种需求已经有一段时间了。当然,在生产环境中,我有点不愿依靠_meta,但这就是生活。谢谢! – jMyles 2014-01-16 02:53:58

7

这是一个黑客攻击的一位,但这个工程:

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

多么美丽的黑客,它救了我的一天。谢谢! – neelix 2016-11-16 07:46:25

0

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

1

要看你会用什么样的模式继承。请参阅 http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance 三种经典种类。因为它听起来像你想要排除抽象基类的Swallow对象。

如果你想不同的信息存储在数据库中的燕子VS AfricanSwallow VS EuropeanSwallow,那么你要使用MTI。 MTI作为官方django模型推荐的最大问题是多态性无法正常工作。也就是说,如果你从数据库中获取一个实际上是AfricanSwallow对象的Swallow对象,那么你将不会得到一个非洲流氓实例。 (请参阅this question。)类似django-model-utils InheritanceManager可以帮助解决这个问题。

如果您有需要通过这种变化以保持实际的数据,使用South migrations。进行两次迁移 - 第一次更改模式,另一次将相应对象的数据复制到子类中。

0

另一个(过时)的方法:如果你不介意保持一方的身份证你可以创建一个从父母的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实例将被创建替换每个初始燕子实例 也许这将帮助别人:)