Django模型inheritance:创build现有实例的子实例(downcast)?
我试图整合一个第三方Django的应用程序,使不幸的决定从django.contrib.auth.models.User
inheritance,这是一个可插拔的应用程序的大禁忌。 引用Malcolm Tredinnick :
更重要的是,虽然,就像在Python中一样,用Django的模型inheritance也不能“倒置”。 也就是说,如果你已经创build了User实例,那么你不能在下面探索一下,使得这个实例对应于你尚未创build的子类实例。
那么,我需要将这个第三方应用程序与我现有的用户实例集成在一起。 所以,如果假设我真的愿意在封面上捅一下,我有什么select? 我知道这是行不通的:
extended_user = ExtendedUser(user_ptr_id=auth_user.pk) extended_user.save()
有没有例外,但它打破了各种各样的东西,首先用空string覆盖django.contrib.auth.models.User
所有列…
这应该工作:
extended_user = ExtendedUser(user_ptr_id=auth_user.pk) extended_user.__dict__.update(auth_user.__dict__) extended_user.save()
在这里,你基本上只是将auth_user版本中的值复制到extended_user中,然后重新保存。 不是很优雅,但它的作品。
如果你不喜欢__dict__.update
解决scheme,你可以这样做:
for field in parent_obj._meta.fields setattr(child_obj, field.attname, getattr(parent_obj, field.attname))
我通过在django用户邮件列表上询问find了这个答案:
https://groups.google.com/d/msg/django-users/02t83cuEbeg/JnPkriW-omQJ
这不是公共API的一部分,但您可以依靠Django如何在内部加载fixture。
parent = Restaurant.objects.get(name__iexact="Bob's Place").parent bar = Bar(parent=parent, happy_hour=True) bar.save_base(raw=True)
请记住,这可能会破坏任何新版本的Django。
我正在使用Django 1.6,而我的ExtendedUser
模型来自OSQA( forum.models.user.User
)。 由于一些奇怪的原因, dict.__update__
和setattr
的上述解决scheme有时会失败。 这可能与我拥有的其他一些模型有关,即在用户表上施加限制。 以下是另外两种可以尝试的解决方法:
解决方法#1:
extended_user = ExtendedUser(user_ptr_id = user.pk) extended_user.save() # save first time extended_user.__dict__.update(user.__dict__) extended_user.save() # save second time
解决方法#2:
extended_user = ExtendedUser(user_ptr_id = user.pk) extended_user.__dict__.update(user.__dict__) extended_user.id=None extended_user.save()
也就是说,如果你设置了pk
和id
,有时候保存新的子实例会失败,但是你可以设置pk
,保存它,然后一切似乎都正常。