【问题标题】:Move a python / django object from a parent model to a child (subclass)将 python / django 对象从父模型移动到子模型(子类)
【发布时间】:2011-04-30 00:00:30
【问题描述】:

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

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

如何移动它们?

【问题讨论】:

    标签: django django-models django-orm


    【解决方案1】:

    这有点小技巧,但这是可行的:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 嘿 - 很棒的答案。我有这个需求已经有一段时间了。自然,我有点不愿意在生产环境中依赖 _meta,但这就是生活。谢谢!
      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          另一种(过时的)方法:如果您不介意保留父母的 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 实例 也许这会对某人有所帮助:)

          【讨论】:

            猜你喜欢
            • 2020-11-16
            • 2012-10-28
            • 1970-01-01
            • 2016-11-06
            • 1970-01-01
            • 2020-01-07
            • 1970-01-01
            • 2022-01-07
            • 1970-01-01
            相关资源
            最近更新 更多