我正在继承现有模型。我希望现在父类的许多成员都是子类的成员。
例如,我有一个模型Swallow。现在,我正在制作EuropeanSwallow(Swallow)和AfricanSwallow(Swallow)。我想采取一些但不是所有Swallow对象使它们成为EuropeanSwallow或AfricanSwallow,这取决于它们是否是迁徙的。
我该如何移动它们?
答案 0 :(得分:8)
这有点像黑客,但这有效:
swallow = Swallow.objects.get(id=1)
swallow.__class__ = AfricanSwallow
# set any required AfricanSwallow fields here
swallow.save()
答案 1 :(得分:6)
我知道这要晚得多,但我需要做类似的事情并且找不到多少。我发现答案隐藏在一些源代码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 :(得分:1)
取决于您将使用哪种模型继承。看到 http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance 对于三种经典种类。因为听起来你想要Swallow对象排除抽象基类。
如果你想在数据库中为Swallow vs AfricanSwallow与EuropeanSwallow存储不同的信息,那么你将需要使用MTI。官方django模型推荐的MTI最大的问题是多态性无法正常工作。也就是说,如果从DB中获取Swallow对象(实际上是AfricanSwallow对象),您将无法获得非洲Swwallow实例。 (参见this question。)django-model-utils InheritanceManager之类的东西可以帮助解决这个问题。
如果您需要通过此更改保留实际数据,请使用South migrations。进行两次迁移 - 首先是一次更改模式,另一次是将相应对象的数据复制到子类中。
答案 3 :(得分:0)
我建议使用django-model-utils's InheritanceCastModel。这是我喜欢的一个实现。你可以在djangosnippets和一些博客中找到更多,但是经过他们所有我选择了这个。希望它有所帮助。
答案 4 :(得分:0)
另一种(过时的)方法:如果你不介意保留父母的身份,你可以从父母的角色创建全新的子实例。这就是我所做的:
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实例 也许这会帮助某人:)