如何将模型转换为其子代理模型的实例
问题描述:
我有一个代理模型。如何将模型转换为其子代理模型的实例
现在我想从其父模型的给定实例转换为代理的实例。
我有我的经理这样的代码:
def from_parent_user(self, user):
instance = Member()
single_fields = self.model._meta.fields
for field in single_fields:
setattr(instance, field.name, getattr(user, field.name))
multiple_fields = self.model._meta.many_to_many
for field in multiple_fields:
setattr(instance, field.name, getattr(user, field.name).all())
return instance
这工作,但复制多对多字段时赚了很多的查询。 所以它甚至不如简单地做这样的:
def from_parent_user(self, user):
return self.get(pk=user.pk)
任何方式复制关系foreing键,高速缓存或东西,避免作出任何查询呢?
我会在几乎每一个请求使用这种方法:/
编辑:
这似乎是工作:
def from_parent_user(self, user):
member = Member()
single_fields = self.model._meta.fields
for field in single_fields:
setattr(member, field.name, getattr(user, field.name))
multiple_fields = self.model._meta.many_to_many
for field in multiple_fields:
# doing this scares me, I don't know if it is safe:
getattr(member, field.name).__dict__.update(getattr(user, field.name).__dict__)
return member
如果有谁知道,如果有多对多这样做管理人员是否安全,请留下评论/回答。
答
查看Django的逻辑之后,我对你的方法只有几个担忧。我也使用类似于你正在做的事情,但是我从模拟字段的创建和关联到新的父模型类的自上而下的方法来解决它。
关注1:
if auto_created:
self.creation_counter = Field.auto_creation_counter
Field.auto_creation_counter -= 1
else:
self.creation_counter = Field.creation_counter
Field.creation_counter += 1
下面是当一个场被初始化发生这种情况的逻辑,django的递增上Field类的静态计数器。据我所看到的,它不应该负的大局观影响你,这是唯一的静态参考我能找到在现场的__init__
方法
关注2:
def __deepcopy__(self, memodict):
# We don't have to deepcopy very much here, since most things are not
# intended to be altered after initial creation.
obj = copy.copy(self)
if self.rel:
obj.rel = copy.copy(self.rel)
memodict[id(self)] = obj
return obj
这种方法是在Field类中找到的,当字段被深度复制时,它会在关系本身上进行复制。我会倾向于相信,他们已经实现了这种级别的复制,其原因可能是为了阻止他们在执行类似于您和我正在尝试添加一些魔法时遇到的任何问题。所以也许不是复制字典,而是执行深层复制,让django的深层复制实现它所需要的额外魔法。除了这两个问题之外,我已经成功移动并将字段复制到新的模型类实例,并且我没有看到“实际”原因,因为实现它的方式应该引起太多关注。如果由于某种原因,你碰上的关系问题,至少你会知道从哪里开始:)
编辑
我创建了一个要点,以帮助说明完全实现:https://gist.github.com/bmoyles0117/5604915
感谢您对布莱恩的贡献。在尝试获取并且无法管理时,我首先查看了copy/deepcopy。你的建议究竟是什么?使用复制/深层复制的字段和many_to_many与2我有类似的循环? – 2013-05-18 13:31:17
我已经为你创建了一个要点,它显示了实现深度拷贝的“utils.py”。我总结了一下你的实现,但至少你可以看到我的方法:) – Bryan 2013-05-18 16:05:07
嘿,thx,我已经在要点留下了评论。 – 2013-05-18 16:33:52