我有代理模型。
现在我想从其父模型的给定实例转换为代理的实例。
我在我的经理中有这个代码:
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)
任何方法都可以复制关键字,缓存或其他东西的关系,并且完全避免进行任何查询?
我将在几乎所有请求中使用此方法:/
编辑:
这似乎有效:
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
如果有人知道这对多对多经理是否安全,请发表评论/回答。
答案 0 :(得分:1)
在查看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类的静态计数器。据我所知,它不应该在大图中对你产生负面影响,这是我在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类中找到,它在深度复制字段时对关系本身进行复制。我倾向于相信他们已经实现了这种级别的复制,这是出于一个非常特殊的原因,也许是为了阻止他们在做类似于你和我试图增加一点魔力的事情时遇到的任何问题。所以也许不是复制dicts,我会执行一个深层复制,让django的深拷贝实现做它需要的额外魔法。
除了这两个问题之外,我已经取得了很好的成功,并将字段复制到新的模型类实例中,我认为没有“真正的”理由说明为什么实现它的方式应引起太多关注。如果由于某种原因你遇到了关系问题,至少你会知道从哪里开始:)
修改强>
我已经创建了一个要点,以帮助说明完整的实施:https://gist.github.com/bmoyles0117/5604915