Django模型继承:创建现有实例的子实例(向下转换)?

Ben*_*end 47 python django inheritance

我正在尝试整合第三方Django应用程序,该应用程序做出了不幸的继承决定django.contrib.auth.models.User,这对于可插拔应用程序来说是一个很大的禁忌.引用Malcolm Tredinnick:

更重要的是,就像在Python中一样,你不能使用Django的模型继承来"低估".也就是说,如果您已经创建了User实例,那么您不能在没有深思熟虑的情况下,使该实例对应于您尚未创建的子类实例.

好吧,我正处于需要将此第三方应用程序与现有用户实例集成的情况.所以,如果假设我确实愿意在封面下捅,我有什么选择?我知道这不起作用:

extended_user = ExtendedUser(user_ptr_id=auth_user.pk)
extended_user.save()
Run Code Online (Sandbox Code Playgroud)

也没有例外,但是它打破了各种各样的东西,首先django.contrib.auth.models.User用空字符串覆盖所有列...

Dan*_*man 66

这应该工作:

extended_user = ExtendedUser(user_ptr_id=auth_user.pk)
extended_user.__dict__.update(auth_user.__dict__)
extended_user.save()
Run Code Online (Sandbox Code Playgroud)

在这里,您基本上只是将auth_user版本中的值复制到extended_user版本中,然后重新保存它.不是很优雅,但它的工作原理.

  • 男人终于下定决心了。在这个问题上卡住了太久。谢谢 (2认同)

pod*_*mok 6

如果你不喜欢__dict__.update解决方案,你可以这样做:

for field in parent_obj._meta.fields
    setattr(child_obj, field.attname, getattr(parent_obj, field.attname))
Run Code Online (Sandbox Code Playgroud)


gue*_*tli 5

我通过询问django用户邮件列表找到了这个答案:

https://groups.google.com/d/msg/django-users/02t83cuEbeg/JnPkriW-omQJ

这不是公共API的一部分,但是您可以依靠Django内部加载夹具的方式。

parent = Restaurant.objects.get(name__iexact="Bob's Place").parent
bar = Bar(parent=parent, happy_hour=True)
bar.save_base(raw=True)
Run Code Online (Sandbox Code Playgroud)

请记住,这可能会因任何新版本的Django而中断。