2010-10-25 72 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實例將被創建替換每個初始燕子實例 也許這將幫助別人:)