代码之家  ›  专栏  ›  技术社区  ›  jMyles

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

  •  6
  • jMyles  · 技术社区  · 14 年前

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

    例如,我有一个燕子模型。现在,我要做欧洲燕子和非洲燕子。我想带一些但不是所有的燕子,根据它们是否是迁徙的,它们要么是欧洲燕子,要么是非洲燕子。

    我如何移动它们?

    5 回复  |  直到 7 年前
        1
  •  6
  •   shapiromatron mkriheli    10 年前

    我知道这要晚很多,但我需要做一些类似的事情,找不到太多。我在一些源代码中找到了答案 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
  •  8
  •   Wogan    14 年前

    这有点像黑客,但这很管用:

    swallow = Swallow.objects.get(id=1)
    swallow.__class__ = AfricanSwallow
    # set any required AfricanSwallow fields here
    swallow.save()
    
        3
  •  1
  •   Community Egal    7 年前

    取决于您将使用哪种模型继承。见 http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance 三种经典款式。因为听起来你想吞咽那些排除抽象基类的对象。

    如果您想在数据库中为燕子vs非洲燕子vs欧洲燕子存储不同的信息,那么您需要使用MTI。正如Django官方模型所建议的那样,MTI最大的问题是多态性不能正常工作。也就是说,如果从数据库中获取一个燕子对象,它实际上是一个非洲燕子对象,那么就不会得到一个非洲燕子实例。(见 this question 比如Django Model Utils InheritanceManager 有助于克服这一点。

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

        4
  •  0
  •   rasca    13 年前

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

        5
  •  0
  •   serguitus    7 年前

    另一种(过时的)方法:如果你不介意保留家长的ID,你可以从家长的属性创建全新的孩子实例。我就是这样做的:

    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实例。 也许这能帮助别人:)